使用MSBuild将多个值传递给Wix DefineConstants属性

使用MSBuild将多个值传递给Wix DefineConstants属性,msbuild,wix,msbuild-task,Msbuild,Wix,Msbuild Task,我目前正在MSBuild中集成我的Wix项目。我有必要将多个值传递给Wix项目。一个值将起作用(以下示例中的ProductVersion) 但是,如何将多个值传递给DefineConstants键?我尝试了所有的“逻辑”分隔符(空格、逗号、分号、管道符号),但都不起作用 有其他人遇到过这个问题吗 不起作用的解决方案: 尝试添加DefineConstants元素无效,因为DefineConstants需要在Properties属性中表示 我想这样的办法应该行得通 <DefineConst

我目前正在MSBuild中集成我的Wix项目。我有必要将多个值传递给Wix项目。一个值将起作用(以下示例中的ProductVersion)


但是,如何将多个值传递给DefineConstants键?我尝试了所有的“逻辑”分隔符(空格、逗号、分号、管道符号),但都不起作用

有其他人遇到过这个问题吗

不起作用的解决方案:

  • 尝试添加DefineConstants元素无效,因为DefineConstants需要在Properties属性中表示

  • 我想这样的办法应该行得通

    <DefineConstants>DEBUG;TRACE</DefineConstants> 调试;痕迹 查看这篇博客文章,看看它是否能帮助你。

    也请查看此论坛帖子。它解决了与您类似的问题。
    为什么要指定DefineContstants=ProductVersion=XXXXXX

    对于未赋值的DefineConstants,要么定义了常量(如调试或跟踪),要么未定义。此属性与C#编译器开关有关。你到底想干什么

    另外,我不知道你说我的博客文章是“黑客”是什么意思,它被构建了两次才是关键

    赛义德·易卜拉欣·哈希米


    我的书:

    问题:

    MSBuild任务(不是MSBuild.exe,是名为MSBuild的MSBuild任务)无法处理WIX项目使用的多个常量。通常,您会在构建脚本中指定以下属性:

    <MSBuild Projects="YourSolution.sln" Properties="Configuration=MyConfig;Platform=x86;DefineConstants=&quot;SOMETHING=1;SOMETHINGELSE=2&quot;" />
    
    因此,当candle尝试使用这些常量时,它通常会响应“error CNDL0150:Undefined preducer variable'$(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;" />
    

    我知道MSDN文档充满了错误,有时会产生误导:下面是它对定义状态的说明

    定义条件编译器 常量。符号/值对为 用分号分隔,是 通过使用以下命令指定 语法:

    symbol1=值1;symbol2=值2

    该属性相当于 /定义编译器开关

    根据MSDN,您可以1.定义多个常量,2.(@Sayed)赋值

    但是,我无法使MSBuild任务的此属性的预期行为按预期工作,并推荐Jeff Winn的变通方法,他的帖子应标记为答案。

    变通方法

    假设:

    • SomeEnumValue的可能值为 EnumValue1和EnumValue2
    在MSBuild中:

    <DefineConstants>Debug;use_$(SomeEnumValue)</DefineConstants>
    
    Debug;使用$(SomeEnumValue)
    
    在WiX中:

    <?ifdef $(var.use_EnumValue1) ?>
      ...
    <?elseif $(var.use_EnumValue2) ?>
      ...
    <?endif?>
    
    
    ...
    ...
    
    使用MSBuild任务生成Visual Studio解决方案时,以下内容对我很有用:

    <MSBuild Projects="Solution.sln"
             Targets="Rebuild"
             Properties="Configuration=Debug;DefineConstants=DEBUG%3bTRACE" />
    
    
    
    诀窍是使用
    %3b
    来转义
    DefineConstants值中的分隔符。我不确定这是否也适用于
    =
    值。它们可能需要作为
    %3d
    转义,或者根本不起作用


    MSBuild元素上还有一个
    TargetAndPropertyListSeparators
    属性。我找不到它的任何文档,但可以使用它设置一个分隔符,而不是

    当我将以下行包括在.wixproj文件(使用Visual Studio 2010)中时,它们起作用

    
    常数1=Value1;常数2=Value2;常数3=Value3
    
    问题在于将名称-值对传递给MSBuild任务,然后让MSBuild正确解析它们,以便将它们传递给Candle任务。MSBuild似乎可以处理简单名称列表或单个名称-值对,但不能处理对列表


    我的解决方案是在将列表传递到MSBuild任务时转义该列表,并在它转到蜡烛任务时再次取消转义该列表

    在MSBuild文件中,在如下属性中定义对:

    <PropertyGroup>
        <WixValues>
            One=1;
            Two=2;
            Three=3;
        </WixValues>
    </PropertyGroup>
    
    <MSBuild ...
        Properties="ProductVersion=%(WixSetups.ISVersion)" />
    
    即使该框中已有其他变量,也可以这样做;只需将其与分号一起添加到列表中即可

    您将在MSBuild日志中看到
    candle.exe
    工具正确接收参数:

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

    您可以将其作为参数传递,而不是常量。代码如下所示:

    <PropertyGroup>
        <WixValues>
            One=1;
            Two=2;
            Three=3;
        </WixValues>
    </PropertyGroup>
    
    <MSBuild ...
        Properties="ProductVersion=%(WixSetups.ISVersion)" />
    
    例如:

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

    这将适用于多个参数。

    这对我来说很有效,允许我传入带有尚未定义的键值对的项。这不是最优雅的,但我不是一个编码员

    msbuild test.proj/p:passedInput=“ProductVersion=45;rt=669;wewanttoknow=test5“


    我在实现这一点上仍然有很多困难,但上面的每个答案都为我的解决方案做出了贡献,所以我想与大家分享

    环境:TFS生成服务器2010-Powershell调用MSBuild.exe Wix 3.6安装在构建服务器上

    目标是将生成版本号和5个目录传递到MSBuild中,以便Candle.exe正确接收它们

    生成在生成结束时调用命令文件,该命令文件包括调用powershell脚本以生成Wix安装程序的步骤。它传入生成的版本号以及源目录和输出目录(输出是UNC fileshare引用\tfsbuildserver..)

    要使其正常工作,请在Powershell ps1文件中

    • candle.exe -dOne=1 -dTwo=2 -dThree=3 -dConfiguration=Release...
      <MSBuild ...
          Properties="ProductVersion=%(WixSetups.ISVersion)" />
      
      <DefineConstants>BuildVersion=$(ProductVersion)</DefineConstants>
      
      $(var.BuildVersion)
      
      <Product Id="*" Name="My Company" Language="1033" Version="$(var.BuildVersion)"... />
      
      <?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>
      
      $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
      
        <Target Name="BeforeBuild">
            <CreateProperty Value="$([MSBuild]::Unescape($(DefineConstants)))">
               <Output TaskParameter="Value" PropertyName="DefineConstants" />
            </CreateProperty>
        </Target>
      
      <MSBuild
          Projects="MyApplication.sln"
          Properties="DefineConstants=Sources=$(OutputPath)\MyApplication\&#59;Configuration=$(Configuration)&#59;OutDir=$(OutputPath)\WiX\"
          Targets="Clean;Rebuild"
      />