2011-12-06 46 views
20

我正在尝试配置WiX安装程序和库,以便库中的一个文件的版本用作产品/ @版本建立。引用从WiX安装项目中的WiX库项目中定义的WixVariable

背景

在具有定义的文件的设置本地在于假定该组件项目由维克斯项目引用的,然后被配置,这是相对简单:

<Component Id="Company.Assembly" Guid="[GUID]"> 
    <File Id="Company.AssemblyFile" 
      Name="Company.Assembly.dll" KeyPath="yes" 
      DiskId="1" 
      Source="$(var.Company.Assembly.TargetPath)" /> 
    </Component> 

然后将产物版本可以设置为

<Product Id="[GUID]" 
      Name="Product Name" 
      Language="1033" 
      Version="!(bind.FileVersion.$(var.Company.AssemblyFile 
        .TargetFileName))" 
      Manufacturer="Company Name" 
      UpgradeCode="[GUID]"> 

发行

因此,将所有组件移至WiX库项目后,不再可以直接引用!(bind.FileVersion.$(var.Company.AssemblyFile.TargetFileName))变量。

我试着在图书馆

WixVariable Id="BuildVersion" Value="!(bind.FileVersion.Company.AssemblyFile)"/> 

配置WixVariable,然后引用从设置

<Product Id="[GUID]" 
      Name="Product Name" 
      Language="1033" 
      Version="!(wix.BuildVersion)" 
      Manufacturer="Company Name" 
      UpgradeCode="[GUID]"> 

没有成功。

在库或设置中是否需要一些额外的步骤或语法来使WixVariable(或它的某些派生)可从设置中访问?

回答

47

我听了很多,我不认为WiX文档在解释情况方面做得特别好,所以就是这样。简短的回答是你的语法是正确的;使用WixVariable元素声明的变量以语法!(wix.VariableName)引用,您可以使用在引用的库中定义的变量,因此!(wix.BuildVersion)对于上面给出的示例是正确的。它不起作用的原因是因为该值需要在编译阶段进行验证,但直到链接阶段才会生成。所以下面是一个很长的答案:

有两种不同类型的变量可以在* .wxs文件中引用; (或连接器)变量。前者用$语法引用,例如$(var.VariableName)和后者是与!语法,例如!(bind.FileVersion.FileId)。关键区别很简单:在编译阶段(通过candle.exe)分析预处理器变量,并在链接阶段(通过light.exe)分析绑定器变量。编译器负责获取源* .wxs文件并将其编译为* .wixobj文件;它不处理实际的有效负载,所以它不能从链接文件中读取版本信息。 * .wixobj文件然后传递给处理有效负载并创建MSI数据库的链接器。链接器负责从有效载荷中收集元数据,这就是为什么它可以为像!(bind.FileVersion.FileId)这样的变量提供值。

请注意,用WixVariable元素声明的变量被引用!语法,所以它是一个活页夹变量;它将可用于light.exe,但不会提供给candle.exe。这是一个问题,因为candle.exe对某些字段(如Product/@ Version)应用验证。它不知道!(wix.BuildVersion)将评估什么,所以它不能验证它会产生有效的版本。相反,您可以脱离!(bind.FileVersion.FileId),因为在编译时蜡烛会在链接时解析为有效版本(FileId是对产品中文件的直接引用,因此蜡烛相信它会存在以产生版本号码链接)。

因此,您可以在* .wxs的其他任何地方使用!(wix.BuildVersion),但不能将其用作Product/@ Version的值。据我所知,你可以在这里使用的唯一绑定变量是!(bind.FileVersion.FileId),但显然这是不好的,如果你想从引用的库中获取值。否则,你只需要从其他地方获取你的版本信息并将其传递到WiX,以便在编译时可用。如果您使用的是MSBuild,它可以通过GetAssemblyIdentity任务查询版本信息,并可以通过DefineConstants属性将其传递给WiX。在* .wixproj文件以下目标应该这样做:

<Target Name="BeforeBuild"> 
    <GetAssemblyIdentity AssemblyFiles="[Path.To.Target.File]"> 
    <Output TaskParameter="Assemblies" ItemName="AsmInfo" /> 
    </GetAssemblyIdentity> 
    <CreateProperty Value="%(AsmInfo.Version)"> 
    <Output TaskParameter="Value" PropertyName="BuildVersion" /> 
    </CreateProperty> 
    <CreateProperty Value="$(DefineConstants)"> 
    <Output TaskParameter="Value" PropertyName="DefineConstantsOriginal" /> 
    </CreateProperty> 
    <CreateProperty Value="$(DefineConstants);BuildVersion=$(BuildVersion)"> 
    <Output TaskParameter="Value" PropertyName="DefineConstants" /> 
    </CreateProperty> 
</Target> 
<Target Name="AfterBuild"> 
    <CreateProperty Value="$(DefineConstantsOriginal)"> 
    <Output TaskParameter="Value" PropertyName="DefineConstants" /> 
    </CreateProperty> 
</Target> 

的BuildVersion属性将被传递给candle.exe这样你就可以用预处理器变量$(var.BuildVersion)引用它。这当然不会像保存在* .wxs文件中一样干净,但它是将版本信息变为蜡烛的一种方式,因此它可以用作Product/@ Version中的变量。我当然想听到更好的方法来做到这一点。

+1

谢谢,非常全面的回答。有趣的是,你还回答了我的后续问题,关于如何将变量写入DefineConstants。 –

1

我使用Heat.exe时,也有类似的问题,这让我重写源变量不与系统的环境变量或搞乱其他如:

"%wix%bin\heat.exe" dir "$(SolutionDir)Web\obj\$(Configuration)\Package" -cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER -var wix.PackageSource="$(SolutionDir)Web\obj\$(Configuration)\Package" -out "$(SolutionDir)WebInstaller\PackageFragment.wxs"

我觉得这句法可以用于任何变量声明将不会在链接时工作:

<wix.YOURVAR="VALUE">-in command line/<!(wix.YOURVAR="VALUE")>-in .WXS files 

也许在其他地方也有帮助。

相关问题