Passing MsBuild Variables to Wix
It almost seems like it would be an easy thing to have wix (an xml file-based installer build system) see and use variables passed to it by a controlling msbuild script (an xml file-based build system). The reality is a bit more difficult.
We started off wanting to have Wix build a package for us based on files in a version-dependent folder. As we change the version number, Wix should look in a different folder for the files. We also wanted this to work on a local (dev) machine and on a build machine running a TFS build agent.
So for a "BuildNumber" maybe an environment variable:
$(env.BuildNumber)
or a plain old wix variable:
$(env.BuildNumber)
Now, we can define a variable in the .wxs source or .wxi include file but none of those are settable from "the outside world" of msbuild or the command line. We have to rely on a built-in wix feature called DefineConstants which is a semi-colon delimited list of key value pairs. Opening the .wixproj in Visual Studio, the project property look like this:
Variables get passed to the wix commandline toolchain using the -d
switch:
So, if you don't have a variable defined, msbuild defaults to an emtpy string, which is maybe not what we want. We can address that by unloading the project and hand editing to introduce a default. The MsBuild idiom for this is to define a property but add a condition to only set it if it doesn't already have a value.
DefineConstants looks like this in the project file:
<PropertyGroup>
<DefineConstants>Debug;NAME=Rob;JOB=Dev;BUILDNUMBER=$(BUILDNUMBER)</DefineConstants>
</PropertyGroup>
We need to define a property upstream of this:
<PropertyGroup>
<BuildNumber Condition=" '$(BuildNumber)' == '' ">1.0.0.9</DefineConstants>
</PropertyGroup>
In the calling MsBuild script we can use the AdditionalProperties
meta data
for a project to pass the variable to wix.
<ItemGroup>
<ProjectList Include="SetupProject1.sln">
<AdditionalProperties>BUILDNUMBER=$(MyBuildNumberFromAssembly)</AdditionalProperties>
</ProjectList>
</ItemGroup>
<Message Text="Build is: $(MyBuildNumberFromAssembly)"/>
<MSBuild Projects="@(ProjectList)"/>
Then we can pull the build number in by reading a text file or reflecting on an assembly version or by reading it from the command line.