I'm currently integrating my Wix projects in MSBuild. It is necessary for me to pass multiple values to the Wix project. One value will work (ProductVersion in the sample below).
<Target Name="BuildWixSetups">
<MSBuild Condition="'%(WixSetups.Identity)'!=''"
Projects="%(WixSetups.Identity)"
Targets="Rebuild" Properties="Configuration=Release;OutputPath=$(OutDir);DefineConstants=ProductVersion=%(WixSetups.ISVersion)" ContinueOnError="true"/>
</Target>
However, how do I pass multiple values to the DefineConstants key? I've tried all the 'logical' separators (space, comma, semi-colon, pipe-symbol), but this doesn't work.
Has someone else come across this problem?
Solutions that don't work:
The problem:
The MSBuild task (not MSBuild.exe, the MSBuild task named MSBuild) cannot handle multiple constants used by WIX projects. Normally you would specify the properties in your build script like:
<MSBuild Projects="YourSolution.sln" Properties="Configuration=MyConfig;Platform=x86;DefineConstants="SOMETHING=1;SOMETHINGELSE=2"" />
What you see however, when looking at the build logs is the MSBuild separates the constants and does not keep the values grouped together like you would expect - similar to:
Task "MSBuild" Global Properties:
Configuration=MyConfig
Platform=x86
DefineConstants="SOMETHING=1
SOMETHINGELSE=2"
So when candle tries to use those constants it typically responds with "error CNDL0150: Undefined preprocessor variable '$(var.SOMETHINGELSE)'. What this means is the MSBuild task is not properly handling properties which contain multiple '=' in the value even when grouped within quotation marks. Without the property value being grouped in quotation marks, they should obviously be treated as separate properties, rather than a single value.
The workaround:
In order to fix this problem, you need to call MSBuild.exe directly and pass those values to it manually.
msbuild.exe /p:Configuration=MyConfig /p:Platform=x86 /p:DefineConstants="SOMETHING=1;SOMETHINGELSE=2" YourSolution.sln
This will get your constants the work the way you want them to, without having to redesign your WiX installation project.
NOTE: If you're only using a single constant you can still use the MSBuild task like so:
<MSBuild Projects="YourSolution.sln" Properties="Configuration=MyConfig;Platform=x86;DefineConstants="SOMETHING=1"" />
The problem lies in passing the name-value pairs to the MSBuild task, and then having MSBuild parse them properly so they can be passed to the Candle task. It seems that MSBuild can handle a list of simple names, or a single name-value pair, but not a list of pairs.
My solution is to escape the list when it's passed into the MSBuild task, and unescape it again when it goes to the Candle task.
In your MSBuild file, define the pairs in a property like this:
<PropertyGroup>
<WixValues>
One=1;
Two=2;
Three=3;
</WixValues>
</PropertyGroup>
When you call the MSBuild task, escape the property (requires MSBuild 4):
<MSBuild
Projects="setup.wixproj"
Properties="WixValues=$([MSBuild]::Escape($(WixValues)))" />
The unescaping has to be done in the wixproj file, but there's no need to edit the file by hand. Just open the project's properties, go to the Build tab, and where it says "Define preprocessor variables", put:
$([MSBuild]::Unescape($(WixValues)))
This works even if there are other variables already in that box; just add this to the list along with a semicolon.
You'll see in the MSBuild log that the candle.exe
tool receives the arguments correctly:
candle.exe -dOne=1 -dTwo=2 -dThree=3 -dConfiguration=Release...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With