Передача нескольких значений в свойство Wix DefineConstants с помощью MSBuild - PullRequest
14 голосов
/ 03 февраля 2009

В настоящее время я интегрирую свои проекты Wix в MSBuild. Мне необходимо передать несколько значений в проект Wix. Будет работать одно значение (ProductVersion в примере ниже).

<Target Name="BuildWixSetups">
    <MSBuild Condition="'%(WixSetups.Identity)'!=''"
                Projects="%(WixSetups.Identity)"
                Targets="Rebuild" Properties="Configuration=Release;OutputPath=$(OutDir);DefineConstants=ProductVersion=%(WixSetups.ISVersion)" ContinueOnError="true"/>
</Target>

Однако как передать несколько значений ключу DefineConstants? Я перепробовал все «логические» разделители (пробел, запятая, точка с запятой, символ трубы), но это не работает.

Кто-нибудь еще сталкивался с этой проблемой?

Решения, которые не работают:

  1. Попытка добавить элемент DefineConstants не работает, поскольку DefineConstants необходимо выразить в атрибуте Properties.

Ответы [ 12 ]

13 голосов
/ 25 ноября 2010

Проблема заключается в передаче пар имя-значение в задачу MSBuild, а затем в том, чтобы MSBuild правильно их проанализировал, чтобы они могли быть переданы в задачу Candle. Похоже, что MSBuild может обрабатывать список простых имен или одну пару имя-значение, но не список пар.

Мое решение состоит в том, чтобы избежать списка, когда он передается в задачу MSBuild, и снова удалить его, когда он перейдет к задаче Candle.

В вашем файле MSBuild определите пары в свойстве следующим образом:

<PropertyGroup>
    <WixValues>
        One=1;
        Two=2;
        Three=3;
    </WixValues>
</PropertyGroup>

Когда вы вызываете задачу MSBuild, экранируйте свойство (требуется MSBuild 4):

<MSBuild 
    Projects="setup.wixproj"
    Properties="WixValues=$([MSBuild]::Escape($(WixValues)))" />

Эскейпинг должен быть сделан в файле wixproj, но нет необходимости редактировать файл вручную. Просто откройте свойства проекта, перейдите на вкладку Build и там, где написано «Определить переменные препроцессора», введите:

$([MSBuild]::Unescape($(WixValues)))

Это работает, даже если в этом поле уже есть другие переменные; просто добавьте это в список вместе с точкой с запятой.

В журнале MSBuild вы увидите, что инструмент candle.exe правильно получает аргументы:

candle.exe -dOne=1 -dTwo=2 -dThree=3 -dConfiguration=Release...
13 голосов
/ 27 апреля 2010

Проблема:

Задача MSBuild (не MSBuild.exe, задача MSBuild с именем MSBuild) не может обрабатывать несколько констант, используемых в проектах WIX. Обычно вы указали бы свойства в вашем скрипте сборки как:

<MSBuild Projects="YourSolution.sln" Properties="Configuration=MyConfig;Platform=x86;DefineConstants=&quot;SOMETHING=1;SOMETHINGELSE=2&quot;" />

Однако вы видите, что при просмотре журналов сборки MSBuild разделяет константы и не объединяет значения, как вы ожидаете, - как:

Task "MSBuild" Global Properties:
Configuration=MyConfig
Platform=x86
DefineConstants="SOMETHING=1
SOMETHINGELSE=2"

Поэтому, когда свеча пытается использовать эти константы, она обычно отвечает «ошибка CNDL0150: неопределенная переменная препроцессора« $ (var.SOMETHINGELSE) »». Это означает, что задача MSBuild неправильно обрабатывает свойства, содержащие несколько «=» в значение, даже если оно сгруппировано в кавычки. Без значения свойства, сгруппированного в кавычки, они, очевидно, должны рассматриваться как отдельные свойства, а не как одно значение.

Обходной путь:

Чтобы решить эту проблему, вам нужно напрямую вызвать MSBuild.exe и передать ему эти значения вручную.

msbuild.exe /p:Configuration=MyConfig /p:Platform=x86 /p:DefineConstants="SOMETHING=1;SOMETHINGELSE=2" YourSolution.sln

Это позволит вашим константам работать так, как вы хотите, без необходимости переделывать проект установки WiX.

ПРИМЕЧАНИЕ. Если вы используете только одну константу, вы все равно можете использовать задачу MSBuild следующим образом:

<MSBuild Projects="YourSolution.sln" Properties="Configuration=MyConfig;Platform=x86;DefineConstants=&quot;SOMETHING=1&quot;" />
3 голосов
/ 30 августа 2012

У меня все еще было много проблем с тем, чтобы заставить это работать, но кусочки каждого ответа, приведенного выше, способствовали моему решению, поэтому я хотел поделиться.

Среда: TFS Build Server 2010 - Powershell, вызывающий MSBuild.exe Wix 3.6 установлен на сервере сборки

Цель состоит в том, чтобы передать номер версии сборки и 5 каталогов в MSBuild, чтобы Candle.exe получал их правильно

Build вызывает командный файл в конце сборки, и этот командный файл включает в себя шаг для вызова сценария powershell для сборки установщика Wix. Он передает номер версии для сборки, а также исходный и выходной каталоги (выходные данные являются ссылкой на файловый ресурс UNC \ tfsbuildserver ..)

Чтобы заставить его работать, в файле Powershell ps1,

  • использовать один / p: DefineConstants =, который начинается с двойного "
  • кодировать все разделительные; как% 3b
  • = нормально закодированы
  • не должно быть никаких дополнительных кавычек вокруг имен файлов с пробелами

    $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
    
    $options = " /p:Configuration=Release /p:Platform=x64 "
    $options = $options + " /p:DefineConstants="""
    $options = $options + "SolutionDir=" + $SourceDir
    $options = $options + "%3bTFSBuildSourceLanding=" + $OutputLocation + "SharepointWebRoot\Landing"
    $options = $options + "%3bTFSBuildSourceLandingAdmin=" + $OutputLocation + "SharepointWebRoot\LandingAdmin"
    $options = $options + "%3bTFSBuildSourceRegistration=" + $OutputLocation + "Extranet_Registration"
    $options = $options + "%3bTFSBuildSourceGAC=" + $OutputLocation + "GAC"
    $options = $options + "%3bTFSBuildSourceSQL=" + $OutputLocation + "SQL"
    $options = $options + "%3bProductVersion=" + $BuildVersion + """" 
    
    
    $build = $msbuild + " ""EUM WIX\EUM Wix.wixproj"" " + $options + " /t:Build"
    $clean = $msbuild + " ""EUM WIX\EUM Wix.wixproj"" " + $options + " /t:Clean"
    
    
    Write-Host "Building Wix Installer..."
    Invoke-Expression $clean
    Invoke-Expression $build
    
  • Внутри файла wixproj мы должны убрать экран (внизу, где говорится, что нужно раскомментировать для изменения)

      <Target Name="BeforeBuild">
          <CreateProperty Value="$([MSBuild]::Unescape($(DefineConstants)))">
             <Output TaskParameter="Value" PropertyName="DefineConstants" />
          </CreateProperty>
      </Target>
    
  • Также обратите внимание, что в Visual Studio я буду использовать параметры отладки, и для этих значений могут быть установлены значения по умолчанию, во вкладке «Создание» «Определить переменные препроцессора»

  • в настройках выпуска этот элемент должен быть пустым, так как он будет передан в командной строке выше.

2 голосов
/ 13 марта 2012

Вы можете передать его как параметр, а не как константу. Код будет выглядеть так:

<MSBuild ...
    Properties="ProductVersion=%(WixSetups.ISVersion)" />

Теперь в проекте WiX добавьте константу:

<DefineConstants>BuildVersion=$(ProductVersion)</DefineConstants>

И используйте его в * .wxs файле, где это необходимо:

$(var.BuildVersion)

Например:

<Product Id="*" Name="My Company" Language="1033" Version="$(var.BuildVersion)"... />

Это будет работать с несколькими параметрами.

2 голосов
/ 13 сентября 2010

При использовании задачи MSBuild для построения решения Visual Studio у меня работает следующее:

<MSBuild Projects="Solution.sln"
         Targets="Rebuild"
         Properties="Configuration=Debug;DefineConstants=DEBUG%3bTRACE" />

Трюк использует %3b для выхода из разделителя ; внутри значения DefineConstants. Я не уверен, что это будет работать и для =. Возможно, их нужно экранировать как %3d, или это может вообще не работать ...

В элементе MSBuild также есть атрибут TargetAndPropertyListSeparators. Я не могу найти какую-либо документацию для него, но может быть возможно использовать его для установки разделителя, отличного от ;.

1 голос
/ 10 ноября 2010

Следующие строки работали, когда я включил их в файл .wixproj (с помощью Visual Studio 2010).

<PropertyGroup>
  <DefineConstants>Const1=Value1;Const2=Value2;Const3=Value3</DefineConstants>
</PropertyGroup>
1 голос
/ 06 мая 2010

Я знаю, что документы MSDN полны ошибок и иногда вводят в заблуждение: вот что говорится о DefineConstants

Определяет условный компилятор константы. Пары символ / значение разделяются точкой с запятой и являются указано с помощью следующего Синтаксис:

symbol1 = value1; символ2 = значение2

Имущество эквивалентно / определить переключатель компилятора.

http://msdn.microsoft.com/en-us/library/bb629394.aspx

Согласно MSDN, вы можете: 1. определить несколько констант и 2. (@Sayed) присвоить значения

ОДНАКО Я не смог заставить ожидаемое поведение этого свойства задачи MSBuild работать так, как ожидалось, и порекомендовать обходной путь Джеффа Винна, и его сообщение следует пометить как ответ.

0 голосов
/ 05 июня 2013

Мое решение - избежать точки с запятой, используя &#59;, таким образом:

<MSBuild
    Projects="MyApplication.sln"
    Properties="DefineConstants=Sources=$(OutputPath)\MyApplication\&#59;Configuration=$(Configuration)&#59;OutDir=$(OutputPath)\WiX\"
    Targets="Clean;Rebuild"
/>
0 голосов
/ 22 июня 2012

Это сработало для меня и позволило мне передавать элементы с еще не определенными парами ключ-значение. Не самый элегантный, но я не кодер.

msbuild test.proj / p: PassedInProp = "ProductVersion = 45; rt = 669; wewanttoknow = test5"

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="Test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
    <test Include="$([MSBuild]::Unescape($(PassedInProp)))" />
  </ItemGroup>
 <Target Name ="Test">
    <CreateItem Include ="$([System.String]::New('%(test.identity)').Split('=')[0])" AdditionalMetadata="value=$([System.String]::New('%(test.identity)').Split('=')[1])">
      <Output TaskParameter="Include" ItemName ="Test2"/>
    </CreateItem>
    <Message Text ="Key: %(test2.identity)  Value: %(test2.value)"/>
  </Target>
</Project>
0 голосов
/ 30 июля 2010

Обходной хак.

Предположения:

  • Возможные значения SomeEnumValue: EnumValue1 и EnumValue2

В MSBuild:

<DefineConstants>Debug;use_$(SomeEnumValue)</DefineConstants>

В WiX:

<?ifdef $(var.use_EnumValue1) ?>
  ...
<?elseif $(var.use_EnumValue2) ?>
  ...
<?endif?>
...