In this post, I show how I’ve managed to integrate WiX into my NAnt build scripts while retaining consistency of versioning.

In most build scenarios, the build script is in charge of versioning. For example, the following NAnt target updates the master build number for a system, leaving the result in the property build.version.

<target name="compile.version"
        description="Update build version">
 
   <version startdate="1 Jan 2006" 
             path="version.txt" 
   prefix="build"/>
 
</target>

Once this target has executed, the next step is to inject the version number into our assemblies and our installers. For .NET assemblies, NAnt has a very useful <asminfo> task which can be used generate source files for C# and Visual Basic that contain the version number.

To achieve the same results for our WiX files, the <echo> task comes to the fore.

<target name="compile.installer">
 
  <!-- Generate a version.wxs file -->
 
  <echo file="${wix.src.dir}\version.wxs" 
        message="&lt;Include&gt;"/>
 
  <echo file="${wix.src.dir}\version.wxs" append="true"
        message="&lt;?define version=&quot;${build.version}&quot; ?&gt;"/>
 
  <echo file="${wix.src.dir}\version.wxs" append="true"
        message="&lt;/Include&gt;"/>
 
  ...
 
</target>

The first <echo> statement overwrites any existing version.wxs file, and the following two <echo> statements append additional lines. If you decipher all the XML encoding, you’ll see that the output file will look something like this:

<Include>
    <?define version="1.2.3.4" ?>
</Include>

With this version file in place, the version can be pulled into the main WXS file with an include directive.

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wix">
 
   <?include version.wxs ?>
 
   ...
 
</Wix>

The last step is to refer to the version number where required, replacing the hard coded values. As a minimum, replace the Version attribute on the Product element.

<?xml version="1.0" encoding="utf-8"?>
<Product Id="????????-????-????-????-????????????" 
         Name="My Example Product" 
         Language="1033" 
         Version="$(var.version)" 
         Manufacturer="Niche Software" 
         UpgradeCode="$(var.UpgradeCode)">
 
  ...
 
</Product>

The version number can also injected into the filename of the final MSI, as can be seen in this build fragment.

<target name="compile.installer">
 
  ...
 
    <exec program="lib\wix\candle.exe" verbose="true">
        <arg value="-out"/>
        <arg file="${wix.tmp.dir}\rbquery.wixobj"/>
        <arg file="${wix.src.dir}\rbquery.wxs"/>
    </exec>
 
    <exec program="lib\wix\light.exe" verbose="true">
        <arg value="-out"/>
        <arg file="${wix.build.dir}\rbquery-${build.version}.msi"/>
        <arg file="${wix.tmp.dir}\rbquery.wixobj"/>
    </exec>
 
</target>

One catch to be aware of is that changing the name of the MSI file requires that each newer version of the installer be a major upgrade. If you want to perform minor updates or patches with your MSIs, the name of the MSI must remain unchanged.

Comments

blog comments powered by Disqus