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 b
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"" />
I think something like this should work.
<DefineConstants>DEBUG;TRACE</DefineConstants>
Check this blog post to see if it can help you out. http://www.sedodream.com/PermaLink,guid,9b1d23aa-6cb2-48cb-a47a-9cef29622676.aspx
Also check this forum post. It solves a similar problem as yours. http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/3f485bf4-1b00-48bf-b5d0-4b83341ce4a6/
Why are you specifying DefineContstants=ProductVersion=XXXXXX?
For DefineConstants you are not assigning values, either a constant (like DEBUG or TRACE) is defined or it is not. This property relates to the /define C# compiler switch. What are you really trying to do?
Also I'm not sure what you mean when you say tha my blog post is a "hack" the fact that it was built twice is the whole point.
Sayed Ibrahim Hashimi
My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build
The following works for me when using an MSBuild task to build a Visual Studio Solution:
<MSBuild Projects="Solution.sln"
Targets="Rebuild"
Properties="Configuration=Debug;DefineConstants=DEBUG%3bTRACE" />
The trick is using %3b
to escape the ;
separator inside the DefineConstants
value. I'm not sure if this will work for the =
too. They may need to be escaped as %3d
or it may not work at all...
There's also a TargetAndPropertyListSeparators
attribute on the MSBuild element. I can't find any documentation for it but it might be possible to use it to set a separator other than ;
.
I know MSDN docs are full of errors and sometimes misleading: here is what it says about DefineConstants
Defines conditional compiler constants. Symbol/value pairs are separated by semicolons and are specified by using the following syntax:
symbol1 = value1 ; symbol2 = value2
The property is equivalent to the /define compiler switch.
http://msdn.microsoft.com/en-us/library/bb629394.aspx
According to MSDN, you can 1. define multiple constants and 2. (@Sayed) assign values
HOWEVER I could not get the expected behaviour of this property of the MSBuild task to work as expected and recommend Jeff Winn's workaround, and his post should be marked as the answer.
My solution is to escape the semicolon using ;
, this way:
<MSBuild
Projects="MyApplication.sln"
Properties="DefineConstants=Sources=$(OutputPath)\MyApplication\;Configuration=$(Configuration);OutDir=$(OutputPath)\WiX\"
Targets="Clean;Rebuild"
/>