Geeks With Blogs
Alex Hildyard

In MSBuild we define properties within a PropertyGroup and reference them with the $() notation. In WiX we have variables with a similar syntax, but which do not natively map to MSBuild properties. When working with WiX installer projects within Visual Studio however you will often want to change a WiX variable into an MSBuild property and vice versa. For example:

  • Case 1: You want to bubble through MSBuild properties (for example, assembly version) into the MSI (referenced within the WiX document with XPath locator //Product/@Version)
  • Case 2: You need to call heat.exe with a custom SourceDir (using the -var parameter). For example, your project produces output files which you want deployed to different directory roots by a single MSI, so you successively harvest files for the various roots by calling heat.exe with a changing -var parameter.

The key things you need to know are:

  • if you open a WiX project and select "Properties", then "Build", the "Define preprocessor variables" text box will inject a DefineConstants property into your project file; these variables are passed to candle.exe (among other things)
  • if you open a WiX project and select "Properties", then "Build", the  "Define variables" text box will inject a WiXVariables property into your project file; these variables are passed to light.exe (among other things)
  • both the DefineConstants and WiXVariables MSBuild properties are semi-colon delimited lists of key/value pairs, and there are various methods -- more or less elegant -- of translating from one to the other

Transforming MSBuild properties into WiX variables (Case 1)
I think the most elegant way to do this is via the Decorator pattern here. This adds a new preprocessor variable derived from an MSBuild property without parsing out the existing ones by simply redefining DefineConstants and appending a new key/value pair to the end of it.

Transforming Wix variables into MSBuild properties (Case 2)
To do the opposite, you can extract a known WiX variable from a semi-colon delimited string of key/value pairs with a code snippet like this:

<Target Name="ExtractEnvironment">
    <!-- Convert the semicolon delimited list of key/vaue pairs into an ItemGroup -->
    <ItemGroup>
      <DefineConstantsKVPairs Include="$(DefineConstants)"/>
    </ItemGroup>
    <!-- Evaluate each key/value pair with task batching, then make a conditional assignment -->
    <PropertyGroup>
      <Environment Condition="$([System.String]::new('%(DefineConstantsKVPairs.Identity)').Contains('ENVIRONMENT='))">$([System.String]::new('%(DefineConstantsKVPairs.Identity)').Split('=')[1])</Environment>
    </PropertyGroup>
<Message Text="Environment is: $(ENVIRONMENT)"/>
  </Target>


Here we've used an ItemGroup to perform an implicit String.Split on the set of key/value constants within the DefineConstants property. We've then used Property functions to parse out the one we want, followed by a conditional assignment to grab just the value part.

Posted on Saturday, March 9, 2013 3:50 PM | Back to top


Comments on this post: Passing data between MSBuild and WiX

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Alex Hildyard | Powered by: GeeksWithBlogs.net