在 WIX 升级期间将文件复制到不同的目录
Copying files to different directory during WIX Upgrade
我一直在为应用程序开发 WIX 安装程序,但在升级的一小部分遇到困难:安装目录中有两个 XML 配置文件,我想将其复制到新的ProgramData 目录(因为它们不会在 ...\Program Files... 中)。
我尝试了几种解决方案,包括不同的 brackets/apostrophes/"
,但都无济于事。当我编译 WIX 安装程序时,我从 CANDLE 收到了一些关于 属性 包含 [CommonAppDataProduct]
和 [PRODUCTNAMEFOLDER]
的警告,但我不确定是否需要一些参考 / 属性从 Product.wxs 中定义的那些目录引用到每个自定义操作。
Product.wxs的片段:
<Product Id="*" Name="$(var.ProductName)" Language="0" Version="$(var.Version)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<InstallExecuteSequence>
<SelfUnregModules/>
<SelfRegModules/>
<Custom Action="CopyConfigFilesToTemp" After="InstallValidate" />
<Custom Action="LaunchDPInstActionx86" Before="InstallFinalize">NOT Installed OR MaintenanceMode="Modify"</Custom>
<Custom Action="CopyConfigFilesFromTemp" After="LaunchDPInstActionx86" />
</InstallExecuteSequence>
</Product>
...
<Fragment>
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="PRODUCTNAMEFOLDER" Name="$(var.ProductName)"/>
</Directory>
</Fragment>
自定义操作 CopyConfigFilesToTemp
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="QuietExec2" Value='"xcopy.exe [PRODUCTNAMEFOLDER]*.xml" %TEMP% /I /Y'/>
<CustomAction Id="CopyConfigFilesToTemp" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/>
</Fragment>
</Wix>
自定义操作 CopyConfigFilesFromTemp
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="QuietExec3" Value='"xcopy.exe %TEMP%\*.xml [CommonAppDataProduct]" /I /Y /R'/>
<CustomAction Id="CopyConfigFilesFromTemp" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/>
</Fragment>
</Wix>
这些自定义操作必须是延迟自定义操作,因为它们试图修改程序文件路径中需要提升权限的内容。安装的唯一具有提升权限的部分是安装的服务器服务器部分,当它正在将文件复制到安装目录时。
如果您打算在操作中使用其中一个 msi 属性,则延迟的自定义操作对它们有特殊要求。
上的 Microsoft 网站
Because the installation script can be executed outside of the installation session in which it was written, the session may no longer exist during execution of the installation script. This means that the original session handle and property data set during the installation sequence is not available to a deferred execution custom action.
这实质上意味着您需要将属性的值放在一个特殊位置,该位置保证在安装的提升部分发生时存在,并且必须以这样一种方式进行格式化,即它知道确切的位置期待获得那个价值。
因此 运行 这些操作必须安排在 InstallInitialize 和 InstallFinalize 之间,并且还必须能够从特殊位置获取 属性 值。
要使用延迟的自定义操作,您只需将执行更改为延迟执行,但是,我们必须添加带有格式化值的特殊 属性,以便您可以从您的内部获取 QuietExec 和 QuietExec2 的值自定义操作。
您需要为每个延迟操作声明一个自定义操作,如下所示:
<CustomAction Id="CustomActionNameHere" Property="CopyConfigFilesToTemp" Value="QuietExec2="xcopy.exe [PRODUCTNAMEFOLDER]*.xml" %TEMP% /I /Y" />
<CustomAction Id="CustomActionNameHere" Property="CopyConfigFilesFromTemp" Value="QuietExec3="xcopy.exe %TEMP%\*.xml [CommonAppDataProduct]" /I /Y /R" />
通常,我将这些名称称为与他们设置 属性 的自定义操作相同的名称,并在名称前加上 "Set" 前缀。 IE: SetCopyConfigFilesFromTemp 和 SetCopyConfigFilesToTemp 以便于找到它们。
您还必须安排这些自定义操作,并且在它们设置属性并匹配条件的操作之前安排它们不会出错。
<Custom Action="SetCopyConfigFilesToTemp" Before="CopyConfigFilesToTemp">
<Custom Action="SetCopyConfigFilesFromTemp" Before="CopyConfigFilesFromTemp">
在自定义操作代码中,您需要使用 session.CustomActionData["PropertyName"]
而不是 session["PropertyName"]
我还会考虑您想要 运行 这些复制命令的情况,因为我认为您在卸载产品或全新安装而非升级时不想执行这些操作。
我一直在为应用程序开发 WIX 安装程序,但在升级的一小部分遇到困难:安装目录中有两个 XML 配置文件,我想将其复制到新的ProgramData 目录(因为它们不会在 ...\Program Files... 中)。
我尝试了几种解决方案,包括不同的 brackets/apostrophes/"
,但都无济于事。当我编译 WIX 安装程序时,我从 CANDLE 收到了一些关于 属性 包含 [CommonAppDataProduct]
和 [PRODUCTNAMEFOLDER]
的警告,但我不确定是否需要一些参考 / 属性从 Product.wxs 中定义的那些目录引用到每个自定义操作。
Product.wxs的片段:
<Product Id="*" Name="$(var.ProductName)" Language="0" Version="$(var.Version)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<InstallExecuteSequence>
<SelfUnregModules/>
<SelfRegModules/>
<Custom Action="CopyConfigFilesToTemp" After="InstallValidate" />
<Custom Action="LaunchDPInstActionx86" Before="InstallFinalize">NOT Installed OR MaintenanceMode="Modify"</Custom>
<Custom Action="CopyConfigFilesFromTemp" After="LaunchDPInstActionx86" />
</InstallExecuteSequence>
</Product>
...
<Fragment>
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="PRODUCTNAMEFOLDER" Name="$(var.ProductName)"/>
</Directory>
</Fragment>
自定义操作 CopyConfigFilesToTemp
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="QuietExec2" Value='"xcopy.exe [PRODUCTNAMEFOLDER]*.xml" %TEMP% /I /Y'/>
<CustomAction Id="CopyConfigFilesToTemp" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/>
</Fragment>
</Wix>
自定义操作 CopyConfigFilesFromTemp
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="QuietExec3" Value='"xcopy.exe %TEMP%\*.xml [CommonAppDataProduct]" /I /Y /R'/>
<CustomAction Id="CopyConfigFilesFromTemp" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/>
</Fragment>
</Wix>
这些自定义操作必须是延迟自定义操作,因为它们试图修改程序文件路径中需要提升权限的内容。安装的唯一具有提升权限的部分是安装的服务器服务器部分,当它正在将文件复制到安装目录时。
如果您打算在操作中使用其中一个 msi 属性,则延迟的自定义操作对它们有特殊要求。
上的 Microsoft 网站Because the installation script can be executed outside of the installation session in which it was written, the session may no longer exist during execution of the installation script. This means that the original session handle and property data set during the installation sequence is not available to a deferred execution custom action.
这实质上意味着您需要将属性的值放在一个特殊位置,该位置保证在安装的提升部分发生时存在,并且必须以这样一种方式进行格式化,即它知道确切的位置期待获得那个价值。
因此 运行 这些操作必须安排在 InstallInitialize 和 InstallFinalize 之间,并且还必须能够从特殊位置获取 属性 值。
要使用延迟的自定义操作,您只需将执行更改为延迟执行,但是,我们必须添加带有格式化值的特殊 属性,以便您可以从您的内部获取 QuietExec 和 QuietExec2 的值自定义操作。
您需要为每个延迟操作声明一个自定义操作,如下所示:
<CustomAction Id="CustomActionNameHere" Property="CopyConfigFilesToTemp" Value="QuietExec2="xcopy.exe [PRODUCTNAMEFOLDER]*.xml" %TEMP% /I /Y" />
<CustomAction Id="CustomActionNameHere" Property="CopyConfigFilesFromTemp" Value="QuietExec3="xcopy.exe %TEMP%\*.xml [CommonAppDataProduct]" /I /Y /R" />
通常,我将这些名称称为与他们设置 属性 的自定义操作相同的名称,并在名称前加上 "Set" 前缀。 IE: SetCopyConfigFilesFromTemp 和 SetCopyConfigFilesToTemp 以便于找到它们。
您还必须安排这些自定义操作,并且在它们设置属性并匹配条件的操作之前安排它们不会出错。
<Custom Action="SetCopyConfigFilesToTemp" Before="CopyConfigFilesToTemp">
<Custom Action="SetCopyConfigFilesFromTemp" Before="CopyConfigFilesFromTemp">
在自定义操作代码中,您需要使用 session.CustomActionData["PropertyName"]
而不是 session["PropertyName"]
我还会考虑您想要 运行 这些复制命令的情况,因为我认为您在卸载产品或全新安装而非升级时不想执行这些操作。