在构建安装程序时,经常需要执行一些自定义的逻辑。WIX提供了支持管理自定义动作的功能,这非常有帮助。尽管如此,要让自定义动作正常工作并不总是那么直接。因此,想分享经验,通过WIXVisual Studio插件(版本v3.7.1217.0)来演示如何实现自定义动作。
将创建一个WIX安装项目和一个C#自定义动作项目。将在安装项目中添加一个虚拟文本文件作为安装内容,并稍微修改自动创建的Product.wxs文件。
首先,来看Product.wxs文件的结构:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WixWithCustomAction" Language="1033" Version="1.0.0.0" Manufacturer="Trifonov" UpgradeCode="60468a7d-6485-4e7e-bf82-503213bc43a8">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Media Id="1" Cabinet="Dummy.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="WixWithCustomAction" Name="WixWithCustomAction">
<Component Id="DummyContent" Guid="ba9028ae-0d3b-4b66-8560-f53330736265">
<!--Add the dummy file as content.-->
<File Id="DummyFile" KeyPath="yes" Source="Dummy.txt" Vital="yes" />
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="Complete" Title="WixWithCustomAction" Level="1">
<ComponentRef Id="DummyContent" />
</Feature>
</Product>
</Wix>
这是解决方案结构。如果构建WixWithCustomAction项目,将会创建WixWithCustomAction.msi文件。运行它后,会在程序文件中创建WixWithCustomAction文件夹,并包含Dummy.txt文件。但现在,想要添加一个自定义动作,该动作将在C:\Temp文件夹中创建一个文件。将为此使用MyCustomActionProject。
让稍微修改CustomAction类:
using Microsoft.Deployment.WindowsInstaller;
using System.IO;
namespace MyCustomActionProject
{
public class CustomActions
{
[CustomAction]
public static ActionResult MyCustomAcion(Session session)
{
session.Log("Executing MyCustomAcion");
File.CreateText(@"c:\temp\installed.txt");
return ActionResult.Success;
}
}
}
现在,只需要从安装程序中调用这个自定义动作。为此,将在安装项目中添加对这个项目的引用。
接下来,将在Product.wxs文件中添加自定义动作。将项目添加为引用后,可以使用这些变量。但是添加自定义动作有点复杂。构建MyCustomActionProject.dll文件后,需要调用MakeSfxCA.exe和sfxca.dll,这些工具位于安装的WiX工具集中,因为DLL需要引用Microsoft.Deployment.WindowsInstaller.dll并附加CustomAction.config。调用MakeSfxCA.exe工具将项目输出打包为MyCustomActionProject.CA.dll(可以在这里找到一些额外的信息)。
由于使用的是"C#Custom Action Project",因此在$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.CA.targets文件中添加了一个导入,它将在构建时创建这个包。要检查这一点,可以构建自定义动作项目并查看输出:
Product.wxs中的自定义动作需要引用.CA.dll文件。这就是为什么不能使用$(var.MyCustomActionProject.TargetPath)作为自定义动作二进制文件的源,而必须像这样构建源路径:
$(var.MyCustomActionProject.TargetDir)$(var.MyCustomActionProject.TargetName).CA.dll
另一种选择是不使用项目引用,而是添加自定义动作输出的完整路径。因此,将向wxs文件添加以下行:
<Binary Id="CustomActionBinary" SourceFile="$(var.MyCustomActionProject.TargetDir)$(var.MyCustomActionProject.TargetName).CA.dll" />
<CustomAction Id="CustomActionId" BinaryKey="CustomActionBinary" DllEntry="MyCustomActionMethod" Execute="deferred" HideTarget="yes" />
<InstallExecuteSequence>
<Custom Action="CustomActionId" Before="InstallFinalize" />
</InstallExecuteSequence>