Позоваване на WixVariable, дефинирана в WiX Library Project от WiX Setup Project

Опитвам се да конфигурирам настройка и библиотека на WiX, така че версията на един от файловете в библиотеката да се използва като Product/@Version в настройката.

Фон

При настройка с файлове, дефинирани локално, това е сравнително лесно, като се приеме, че проектът на компонента е препратен от WiX проекта и след това е конфигуриран:

  <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 в библиотеката

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

И след това препратете това от настройката

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

Без успех.

Необходима ли е някаква допълнителна стъпка или синтаксис в библиотеката или настройката, за да се направи WixVariable (или някакво нейно производно) достъпно от настройката?


person Michael Phillips    schedule 06.12.2011    source източник


Отговори (2)


Чувам това много често и не мисля, че документацията на 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), защото candle е удовлетворен по време на компилиране, че ще разреши валидна версия по време на връзката (FileId е директна препратка към файл в продукта, така че candle вярва, че той ще съществува, за да даде версия номер на връзката).

Така че можете да използвате !(wix.BuildVersion) навсякъде другаде във вашия *.wxs, но не можете да го използвате като стойност за Product/@Version. Доколкото знам, единствената свързваща променлива, която можете да използвате тук, е !(bind.FileVersion.FileId), но очевидно това не е добро, ако искате да получите стойността от референтна библиотека. В противен случай просто ще трябва да вземете информацията за вашата версия от някъде другаде и да я предадете на WiX, така че да е налична по време на компилиране. Ако използвате MSBuild, той може да поиска информация за версията със задачата GetAssemblyIdentity и може да предаде това на WiX чрез свойството DefineConstants. Следните цели във вашия *.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, но е един от начините за получаване на информацията за версията в candle, така че да може да се използва като променлива в Product/@Version. Със сигурност бих искал да чуя по-добри начини за това.

person Anon    schedule 19.12.2011
comment
Благодаря, много изчерпателен отговор. Колкото и да е странно, вие също така отговорихте на моя последващ въпрос за това как да напиша променлива в DefineConstants. - person Michael Phillips; 19.12.2011

Имах подобен проблем, когато използвах 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

Може би е полезно и на други места.

person Martin Clemens Bloch    schedule 28.05.2013