这个系列的第一篇文章,向大家演示了一个最简单的WiX实例.这一篇开始,作为一个逻辑上的延展,我们有义务让WiX引擎知道去哪里取得需要打包的文件. 更深入的,我们需要让WiX在编译生成的时候,动态的知道一些信息.传递动态信息的方法归结起来, 一般有2种方式: 替换法和参数法.
现在, 假设我们需要让WiX脚本知道, 当前生成的安装包的版本号是什么 - 这是必要的,因为最终生成的安装包的版本依赖于这个版本号. 而每次生成程序或者程序集的编译过程中所使用的版本号各不相同, 所以他是动态的. 我们看一下这个属性如何从外部传送到WiX脚本内.
还是拿上一篇稍稍修改的WiX脚本文件(wixdemo.wxs)做例子:
1. 替换法.
使用替换法,可以在每个.wxs文件的开始部分填写一个默认的属性及其值,然后在编译这个wxs文件之前,及时的替换掉默认值, 一般可以这么写:
<?xml version="1.0" encoding="utf-8"?>
<?define VERSION="%BUILDNUMBER%"?>
<?define SOURCEDIR="%SOURCEDIR%"?>
<Wix xmlns="http://schmeas.microsoft.com/wix/2003/01/wi">
<Product Name="WixDemo" Id="904F998D-B3BE-4536-9ABE-F8B72B98BCEA"
Language="1033" Version="$(var.VERSION)" Manufacturer="Wix Demo Corp.">
<Package Id="4DB93456-952B-4463-BFD0-86306D5C29D4" Keywords="Installer"
Description="Our road to first wix installer" Comments="We will rock you"
Manufacturer="Our Corp." InstallerVersion="100" Languages="1033"
Compressed="yes" SummaryCodepage="1252" />
<Media Id="1" Cabinet="OMSimulator.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<!--Write a new key to registry on installation and remove it when unstallation-->
<Component Id="RegComponent" Guid="6EEBA57B-A0B0-4328-A414-931A14904913" DiskId="1">
<Registry Id="SignatureKey" Root="HKLM"
Key="SOFTWARE\WixDemo\MySignature"
Action="createKeyAndRemoveKeyOnUninstall" />
</Component>
<!--Target Directory: ProgramFile\Wix Demo Application-->
<Directory Id="WIXDEMO" Name="WixDemo" LongName="Wix Demo Application">
<!--File to be copied-->
<Component Id="WixApp" Guid="C03083B7-E539-47b3-84C6-88ED783A5C31">
<File Id="File_1"
Name="Readme"
LongName="Readme.txt"
KeyPath="no"
Compressed="yes"
src="$(var.SOURCEDIR)\"
DiskId="1"/>
</Component>
</Directory >
</Directory>
</Directory>
<Feature Id="DemoFeature" Title="This feature installs the components for WiX demo" Level="1">
<ComponentRef Id="RegComponent"/>
<ComponentRef Id="WixApp" />
<ComponentRef Id="Config" />
</Feature>
<Property Id="INSTANCE" Value="." />
<Property Id="DEMODB" Value="WixDemoDB" />
</Product>
</Wix>
我们在进行编译之前,需要及时的替换掉%BUILDNUMBER%和%SOURCEDIR%. 这做起来很容易,你可以写C# code来做,也可以使用别的方法. 不过如果你用的编译环境是TFS, 或者更宽泛的说,是基于MSBuild引擎或者NTBuild引擎, 那么你可以直接使用Microsoft SDC tasks library, 放心,这个task library是免费的, 而且有很多额外的奖励^_^.
在编译脚本里面的适当地方(在编译wix脚本之前)添加上这么几行:
<UsingTask TaskName="File.Regex"
AssemblyFile="$(TeamBuildRefPath)\Microsoft.Sdc.Tasks.dll" />
<File.Regex Path="$(WixScriptFolder)\wixdemo.wxs"
RegularExpression="%BUILDNUMBER%"
NewValue="1.1.0.1" />
<File.Regex Path="$(WixScriptFolder)\wixdemo.wxs"
RegularExpression="%SOURCEDIR%"
NewValue="C:\BuildDir\Output" />
这里为了示例,直接使用了具体的buildnumber和输出目录, 你可以而且应该使用来自于编译环境中的有关属性变量, 比如, $(BuildNumber)等.
2. 传递参数法.
wix毕竟是一个引擎, 它本质上还是一个基于命令行的程序, 我们可以给这个命令行程序传递参数来实现向wix脚本传递动态属性的目的.
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schmeas.microsoft.com/wix/2003/01/wi">
<Product Name="WixDemo" Id="904F998D-B3BE-4536-9ABE-F8B72B98BCEA"
Language="1033" Version="$(var.VERSION)" Manufacturer="Wix Demo Corp.">
<Package Id="4DB93456-952B-4463-BFD0-86306D5C29D4" Keywords="Installer"
Description="Our road to first wix installer" Comments="We will rock you"
Manufacturer="Our Corp." InstallerVersion="100" Languages="1033"
Compressed="yes" SummaryCodepage="1252" />
<Media Id="1" Cabinet="OMSimulator.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<!--Write a new key to registry on installation and remove it when unstallation-->
<Component Id="RegComponent" Guid="6EEBA57B-A0B0-4328-A414-931A14904913" DiskId="1">
<Registry Id="SignatureKey" Root="HKLM"
Key="SOFTWARE\WixDemo\MySignature"
Action="createKeyAndRemoveKeyOnUninstall" />
</Component>
<!--Target Directory: ProgramFile\Wix Demo Application-->
<Directory Id="WIXDEMO" Name="WixDemo" LongName="Wix Demo Application">
<!--File to be copied-->
<Component Id="WixApp" Guid="C03083B7-E539-47b3-84C6-88ED783A5C31">
<File Id="File_1"
Name="Readme"
LongName="Readme.txt"
KeyPath="no"
Compressed="yes"
src="$(var.SOURCEDIR)\"
DiskId="1"/>
</Component>
</Directory >
</Directory>
</Directory>
<Feature Id="DemoFeature" Title="This feature installs the components for WiX demo" Level="1">
<ComponentRef Id="RegComponent"/>
<ComponentRef Id="WixApp" />
<ComponentRef Id="Config" />
</Feature>
<Property Id="INSTANCE" Value="." />
<Property Id="DEMODB" Value="WixDemoDB" />
</Product>
</Wix>
上面这个脚本和第一个脚本的区别是开头去掉了默认属性, 那么我们该如何传递呢?
实际上, 只要我们在使用wix命令的时候,加上-d接这个参数就可以了:
<Exec Command="$(WixTool)\candle.exe $(WixScriptFolder)\wixdemo.wxs -dVERSION=1.1.0.1 -dSOURCEDIR=c:\BuildDir\Output /nologo"
WorkingDirectory="$(WixScriptFolder)"/>
<Exec Command="$(WixTool)\light.exe $(WixScriptFolder)\wixdemo.wixobj $(WixTool)\sca.wixlib $(WixTool)\wixca.wixlib /out wixdemo.msi /nologo"
WorkingDirectory="$(WixScriptFolder)"/>
总结: 传递动态属性的基本方法就是这两类. 在一些集成环境中,你可能遇到一些神出鬼没的属性, 它们最终总会归结为这两类中的一类, 比如常见的CoreXT当中的PackageTarget, 比如TFS当中的PackageBinaries Targets等.
需要特别注意的是,属性有公有和私有之分,所有需要传递的属性都是公有属性. 所有的公有属性都应该完全大写!