Ссылка на переменную WixVariable, определенную в проекте библиотеки WiX, из проекта установки WiX

Я пытаюсь настроить установку и библиотеку 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