Ответ 1
Я слышу это много, и я не думаю, что документация WiX особенно хорошо объясняет ситуацию, так что вот оно. Короткий ответ заключается в том, что ваш синтаксис правильный; переменная, объявленная с элементом WixVariable
, ссылается на синтаксис !(wix.VariableName)
, и вы можете использовать переменные, которые были определены в справочной библиотеке, поэтому !(wix.BuildVersion)
верен для примера, приведенного выше. Причина, по которой он не работает, заключается в том, что значение нужно проверять на этапе компиляции, но оно не создается до фазы связывания. Итак, вот длинный ответ:
Существует два разных типа переменных, которые вы можете ссылаться в файле *.wxs; препроцессорные переменные и связующие (или линкерные) переменные. Первый ссылается на синтаксис $, например. $(var.VariableName)
, и последний ссылается на! синтаксис, например. !(bind.FileVersion.FileId)
. Основное различие прост: переменные препроцессора анализируются во время фазы компиляции (с помощью candle.exe), а переменные связующего обрабатываются во время фазы ссылки (by light.exe). Компилятор отвечает за загрузку исходных файлов *.wxs и их компиляцию в файлы *.wixobj; он не обрабатывает фактическую полезную нагрузку, чтобы он не мог читать информацию о версии из связанного файла. Файлы *.wixobj затем передаются в компоновщик, который обрабатывает полезную нагрузку и создает базу данных MSI. Компонент отвечает за сбор метаданных из полезной нагрузки, поэтому он может предоставлять значения для таких переменных, как !(bind.FileVersion.FileId)
.
Обратите внимание, что переменная, объявленная с элементом WixVariable
, ссылается на! синтаксис, так что это переменная связующего; он будет доступен для light.exe, но он не будет доступен для candle.exe. Это проблема, потому что candle.exe применяет проверку на определенные поля, такие как Product/@Version. Он понятия не имеет, что будет оценивать !(wix.BuildVersion)
, поэтому он не может проверить, что он даст допустимую версию. Напротив, вы можете уйти с !(bind.FileVersion.FileId)
, потому что свеча во время компиляции удовлетворена тем, что она разрешит действительную версию во время соединения (FileId - это прямая ссылка на файл в продукте, поэтому свеча надеется, что она будет существовать, чтобы номер версии по ссылке).
Таким образом, вы можете использовать !(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, но это один из способов получить информацию о версии в свечу, чтобы ее можно было использовать как переменную в Product/@Version. Я, конечно, хотел бы услышать лучшие способы сделать это.