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:


or a plain old wix variable:


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:


We need to define a property upstream of this:

    <BuildNumber Condition=" '$(BuildNumber)' == '' "></DefineConstants>

In the calling MsBuild script we can use the AdditionalProperties meta data for a project to pass the variable to wix.

      <ProjectList Include="SetupProject1.sln">

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