2011-12-06 45 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 

也許在其他地方也有幫助。

相關問題