Подтвердить что ты не робот

Передача нескольких значений в свойство Wix DefineConstants с помощью MSBuild

В настоящее время я интегрирую свои проекты 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? Я пробовал все "логические" разделители (пробел, запятая, полуколония, символ трубы), но это не работает.

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

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

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

Ответ 1

Проблема:

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

<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"

Итак, когда свеча пытается использовать эти константы, она обычно отвечает "error CNDL0150: Undefined препроцессорная переменная" $(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;" />

Ответ 2

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

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

В файле MSBuild определите пары в свойстве, подобном этому:

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

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

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

Unescaping необходимо выполнить в файле wixproj, но нет необходимости редактировать файл вручную. Просто откройте свойства проекта, перейдите на вкладку "Сборка" и где говорится "Определить переменные препроцессора", поставьте:

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

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

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

candle.exe -dOne=1 -dTwo=2 -dThree=3 -dConfiguration=Release...

Ответ 3

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

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

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

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

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

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

    $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 мы должны unescape (вниз внизу, где он говорит, чтобы раскомментировать для изменения)

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

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

Ответ 4

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

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

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

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

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

$(var.BuildVersion)

Например:

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

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

Ответ 5

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

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

symbol1 = value1; symbol2 = value2

Свойство эквивалентно /define компилятор.

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

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

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

Ответ 6

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

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

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

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

Ответ 7

Я думаю, что что-то вроде этого должно работать.

 <DefineConstants>DEBUG;TRACE</DefineConstants> 

Отметьте это сообщение в блоге, чтобы узнать, может ли он помочь вам. http://www.sedodream.com/PermaLink,guid,9b1d23aa-6cb2-48cb-a47a-9cef29622676.aspx

Также проверьте этот форум. Он решает аналогичную проблему, как ваша. http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/3f485bf4-1b00-48bf-b5d0-4b83341ce4a6/

Ответ 8

Обходной взлом.

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

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

В MSBuild:

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

В WiX:

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

Ответ 9

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

<PropertyGroup>
  <DefineConstants>Const1=Value1;Const2=Value2;Const3=Value3</DefineConstants>
</PropertyGroup>

Ответ 10

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

<MSBuild
    Projects="MyApplication.sln"
    Properties="DefineConstants=Sources=$(OutputPath)\MyApplication\&#59;Configuration=$(Configuration)&#59;OutDir=$(OutputPath)\WiX\"
    Targets="Clean;Rebuild"
/>

Ответ 11

Почему вы указываете DefineContstants = ProductVersion = XXXXXX?

Для DefineConstants вы не назначаете значения, либо константа (например, DEBUG или TRACE) определена, либо нет. Это свойство относится к коммутатору /define. Что вы действительно пытаетесь сделать?

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

Сказал Ибрагим Хашими

Моя книга: Внутри Microsoft Build Engine: использование MSBuild и Team Foundation Build

Ответ 12

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

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>