Wix延迟了自定义操作访问被拒绝

时间:2018-06-24 13:35:43

标签: wix windows-installer

背景:客户已更改了应用程序的名称。该应用程序已将文件存储在AppData文件夹下,现在需要将该文件夹复制到新名称(并删除旧名称)。

我使用Wix 3.6安装了MSI。我没有找到复制文件夹(仅文件)的标准方法。因此,我一直在尝试使用xcopy命令进行自定义操作,但这似乎很难。

如果我立即建立CA,并在InstallFinalize之后安排它,则可以在WinXP上运行,但只能在Win7上以MSI作为管理员运行。

如果我创建了一个延迟的CA,则会出现拒绝访问错误。即使我测试要在用户文件夹下的文件夹中复制和复制,也会出现此错误。但是如果我使用echo命令对其进行测试,则延迟的CA将成功。

<CustomAction Id="CopyFolder_PropertyAssign" Property="CopyFolder" 
 Value="&quot;[SystemFolder]cmd.exe&quot; /c xcopy 
        &quot;[$(var.PlatformCommonAppDataFolder)]OldName&quot; 
        &quot;[$(var.PlatformCommonAppDataFolder)]NewName&quot; 
        /s /i /h /k /o /y" />
<CustomAction Id="CopyFolder" BinaryKey="WixCA" DllEntry="CAQuietExec" 
 Execute="deferred" Return="check" Impersonate="no" />

<Custom Action="CopyFolder_PropertyAssign" Before="InstallFinalize"></Custom>
<Custom Action="CopyFolder" After="CopyFolder_PropertyAssign"></Custom>

CAQuietExec:  Access denied
CAQuietExec:  Error 0x80070004: Command line returned an error.
CAQuietExec:  Error 0x80070004: CAQuietExec Failed

除了拒绝访问外,还必须有其他原因,因为在用户文件夹下也会发生同样的事情,但是到底是什么呢?

或者为此有其他解决方案(除了创建exe程序包)?

编辑:

该文件夹位于所有用户AppData下。

编辑:

这似乎是不可能的。选择的解决方法是立即建立CA并指导用户以admin身份启动安装程序(或者在大多数情况下应该如此)。无论如何,谢谢您的帮助!

2 个答案:

答案 0 :(得分:1)

推迟到AppDataFolder的自定义操作副本可能会失败,因为您正在运行带有系统帐户的推迟操作,因此它正在尝试访问该系统帐户的用户AppDataFolder。请注意,0x80070004不会被拒绝访问,它是“系统无法打开文件。”

直接CA将失败,因为默认情况下这些CA不会提升,因此显然访问需要提升。

此问题的通常解决方案是将CopyFile元素与一起使用,使用这些位置的目录定义将文件从旧位置复制到新位置。如果将delete设置为yes,它将移动文件,并从旧位置删除它们。

正如Stein指出的那样,这实际上应该在较新版本首次运行时由应用程序完成。数据迁移确实是应在应用程序中解决的应用程序问题,而不是使安装过载。除了您遇到的困难外,如果安装失败并回滚(还原已删除的文件?)以及其他可能无法预料的文件,还可能会出现问题。

答案 1 :(得分:0)

应用程序启动顺序 :如果这些是 userprofile files -换句话说,应用程序的启动用户可以写-最好在应用程序启动顺序中进行此清理。 Crucially this will make the operation run for every users, and not just the user installing the setup 。忘记对包装盒上的所有用户进行重命名是一个常见的错误。假设这些是每个用户的文件(每个用户的副本),而不是%ALLUSERSPROFILE%中所有用户的共享文件(仅管理员用户可写)。

MSI复杂度 :请不要在设置中执行此操作。 MSI具有模拟和运行时行为,非常复杂-这就是导致您看到的神秘错误消息的原因。如果可以使用应用程序启动序列中的用户权限来完成设置,则绝对没有理由在设置中执行此操作。 您只是在应用程序启动时重命名文件夹,应该这样做吗? 应用程序启动代码更容易实现实现,并且非常容易实现<比自定义操作(尤其是延迟模式的自定义操作)强。如果需要,您还可以提供交互式错误消息(与写入日志的错误相反-或根本没有日志)。

实现 :显然要提防应用程序启动代码错误,方法是一旦有问题的用户重命名完成,就可能在注册表中设置一个标志-为了禁用此功能从多次运行中重命名操作。漫游配置文件可能会导致问题,请确保将操作设置为至少每台机器运行一次。您还可以将标志写入appdata文件夹层次结构的非漫游部分吗?那可能更好。当然可以。应该不会引发任何漫游问题。

挑战 :仅有几个挑战:

  • Locks? :应用程序启动时会出现文件/文件夹锁定吗?也许?捕获异常,通知用户,关机然后重试?拒绝启动直到可以进行重命名?可以接受吗?
  • Old application launch? :这很重要吗?有些人尝试符号链接-我的两分钱-他们是魔鬼的作品:-)。我想问题是,如果旧应用程序找不到其文件会发生什么?它甚至可以启动吗?第二个问题是:在“清理”之后,旧应用程序不能正常运行根本不重要吗?