When you’re building (and updating) a software product for release, it’s important that the version number is adjusted as you add features and fix bugs. Your users need to know if the code they have is out of date, and the easiest way for them to tell is to compare version numbers.

You can manually update version, revision, and build numbers in Visual Studio each time you make a change to your application, but that can get inefficient (and annoying) very quickly. Throw WiX into the equation, and you’ve got a couple more places to change the version number by hand.

There are a number of plug-ins for Visual Studio that allow you to set auto-increment rules for assembly version numbers (I like this one), so we won’t start there. Let’s look at how to get the build number from our Add-In project to our WiX-output installer file.

NOTE: I’ve since changed the way I do this. Read this post for the background, and then look here for my current solution. 

Assembly Information

So where is our version number kept? In the properties of our main Add-In project. Right-click the project, choose Properties and then on the Application tab click Assembly Information.

This is the information that gets displayed when a user right-clicks your final Add-In assembly and chooses Properties. Some of these fields will be familiar to you.

image

In this picture, I’ve got a Visual Studio plug-in incrementing the Version numbers automatically, every time I build the project. You can change these numbers manually if you don’t want to use an automated tool.

 

Hard-coded version numbers in a WiX project

Here’s the header for a standard WiX .wxs file. Note the hard-coded Version number. This version number is what users see in the Windows Home Server console when adding or removing an Add-In, so it’s important to keep it up to date.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product
    Name="Windows Home Server Disk Management Add-In"
    Id="*"
    UpgradeCode="{EB6B8302-C06E-4bec-ADAC-932C68A3A98D}"
    Manufacturer="Sam Wood - Tentacle Software"
    Version="1.1.0.9"
    Language="1033">
    <Package
      Manufacturer="Sam Wood - Tentacle Software"
      InstallerVersion="200"
      Languages="1033"
      Compressed="yes" />

The output filename for a WiX project is also hard-coded in the properties of the project.

image

When updating my installer project for a new release, I have to change the Version number in the .wxs file, as well as the Output Name in the project properties. Not too bad, but it gets old quickly.

 

Automatic version numbers in a WiX project.

So how do we automate this versioning process? Getting the right version number inside the finished installer package is easy, and naming the output file based on a version number is only a little bit harder.

Firstly, you need to replace your hard-coded Version with a bind variable. The last property in !(bind.FileVersion.xxx) below represents the WiX File Id you’ve defined further down in your .wxs, and is the file that you’re going to pull your Version number from.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product
    Name="Windows Home Server Disk Management Add-In"
    Id="*"
    UpgradeCode="{EB6B8302-C06E-4bec-ADAC-932C68A3A98D}"
    Manufacturer="Sam Wood - Tentacle Software"
    Version="!(bind.FileVersion.HomeServerConsoleTabDiskMgtDll)"
    Language="1033">
    <Package
      Manufacturer="Sam Wood - Tentacle Software"
      InstallerVersion="200"
      Languages="1033"
      Compressed="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder" Name="PFiles">
        <Directory Id="WHS" Name="Windows Home Server">
          <Component Id="HomeServerConsoleTab.DiskMgt" Guid="{908B7199-DE2A-4dc6-A8D0-27A5AE444FEA}">
            <File Id="HomeServerConsoleTabDiskMgtDll" Source="..\HomeServerConsoleTab.DiskMgt\bin\Release\HomeServerConsoleTab.DiskMgt.dll" Vital="yes" KeyPath="no" DiskId="1"/>

Note that the File Id="HomeServerConsoleTabDiskMgtDll" on line 20 matches the Id we’re using in our !(bind.FileVersion.HomeServerConsoleTabDiskMgtDll) bind variable on line 8.

Now, every time we build this installer project, WiX will bind the Version number to the FileVersion property of HomeServerConsoleTab.DiskMgt.dll (which we set in the Add-In project’s properties). That takes care of the version number that shows up in the Windows Home Server Console.

 

Automatic installer file names in a WiX project

Changing the file name of our installer based on a version number follows much the same process, except we modify the XML of the .wixproj file directly.

NOTE: I’ve since changed the way I do this. Read this post for the background, and then look here for my current solution. 

In Visual Studio, right-click your WiX project and choose Unload Project. The project will show up as (unavailable). Right-click the project again and choose Edit projectname.wixproj to open the project file for editing.

You’ll see XML that looks similar to this:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <ProductVersion>3.0</ProductVersion>
    <ProjectGuid>{e32ee94d-4ba9-4588-a855-e8d70eb8ee04}</ProjectGuid>
    <SchemaVersion>2.0</SchemaVersion>
    <OutputName>WHSDiskManagement.1.1.0.9</OutputName>
    <OutputType>Package</OutputType>
    <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.0\Wix.targets</WixTargetsPath>
    <WixToolPath>$(ProgramFiles)\Windows Installer XML v3\bin\</WixToolPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <OutputPath>bin\Debug\</OutputPath>
    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
    <DefineConstants>Debug</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
    <OutputPath>bin\Release\</OutputPath>
    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="WHSDiskManagement.wxs" />
  </ItemGroup>
  <Import Project="$(WixTargetsPath)" />
</Project>

There are a bunch of comments near the bottom of the file referencing BeforeBuild and AfterBuild actions. We’re going to set up an AfterBuild action that renames the output file.

After the Import Project directive, and before the closing Project tag, add the following AfterBuild Target:

<Target Name="AfterBuild">
  <GetAssemblyIdentity AssemblyFiles="..\HomeServerConsoleTab.DiskMgt\bin\$(Configuration)\HomeServerConsoleTab.DiskMgt.dll">
    <Output TaskParameter="Assemblies" ItemName="AssemblyVersion"/>
  </GetAssemblyIdentity>

  <Copy SourceFiles=".\bin\$(Configuration)\$(OutputName).msi" DestinationFiles=".\bin\$(Configuration)\WHSDiskManagement.%(AssemblyVersion.Version).msi" />
  <Delete Files=".\bin\$(Configuration)\$(OutputName).msi" />
</Target>

Note the file path on line 2. This is the file we’re interrogating for version numbers; you’ll see that it’s the same file that we referenced in the .wxs XML above, and it will have the same relative path.

Line 6 shows the file name we’ll be building: WHSDiskManagement.CurrentVersionNumber.msi. This will gives us something like WHSDiskManagement.1.1.0.9.msi. You can use whatever file naming conventions you like here, of course.

I also changed the OutputName property to “temp” at the same time. That’s not necessary, but it means I can quickly spot the temporary installer file and delete it if necessary.

Your .wixproj XML will now look something like this:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <ProductVersion>3.0</ProductVersion>
    <ProjectGuid>{e32ee94d-4ba9-4588-a855-e8d70eb8ee04}</ProjectGuid>
    <SchemaVersion>2.0</SchemaVersion>
    <OutputName>temp</OutputName>
    <OutputType>Package</OutputType>
    <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.0\Wix.targets</WixTargetsPath>
    <WixToolPath>$(ProgramFiles)\Windows Installer XML v3\bin\</WixToolPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <OutputPath>bin\Debug\</OutputPath>
    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
    <DefineConstants>Debug</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
    <OutputPath>bin\Release\</OutputPath>
    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="WHSDiskManagement.wxs" />
  </ItemGroup>
  <Import Project="$(WixTargetsPath)" />

  <!--To modify your build process, add your task inside one of the targets below and uncomment it.
	Other similar extension points exist, see Wix.targets.-->
  <!--<Target Name="BeforeBuild">
  </Target>-->
  
  <Target Name="AfterBuild">
    <GetAssemblyIdentity AssemblyFiles="..\HomeServerConsoleTab.DiskMgt\bin\$(Configuration)\HomeServerConsoleTab.DiskMgt.dll">
      <Output TaskParameter="Assemblies" ItemName="AssemblyVersion"/>
    </GetAssemblyIdentity>

    <Copy SourceFiles=".\bin\$(Configuration)\$(OutputName).msi" DestinationFiles=".\bin\$(Configuration)\WHSDiskManagement.%(AssemblyVersion.Version).msi" />
    <Delete Files=".\bin\$(Configuration)\$(OutputName).msi" />
  </Target>
</Project>

What is this AfterBuild thing doing? Basically, when the build is complete, we use GetAssemblyIdentity to find the identity of our Add-In assembly, and then use its File Version property as part of a Copy operation to set the installer’s file name (line 36) to include the version number of our Add-In.

Finally, we Delete the original installer file. Not strictly necessary, but I like clean project folders.

Save the changes you’ve made to the .wixproj file, right-click the project in Solution Explorer again, and choose Reload Project.

 

Completion

From now on all you need to do is build the WiX installer project, and you’ll get an installer file that is named correctly, and has the correct version number applied to it.

When you want to change the version number of your Add-In in the future, all you need to do is modify the Assembly Information of your Add-In project.

posted on Sunday, May 03, 2009 11:05 AM | Filed Under [ Windows Home Server Development ]

Comments

Gravatar
# re: Automated installer version numbers for WiX (Alex Kuretz @ 5/8/2009 4:21 AM)

Thanks for this, Sam, I knew all this was possible but hadn't investigated and it's nice to have it summarized in one place.
 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 5/8/2009 10:16 AM)

I stayed up until 2:00 AM trying to get it to work, so I figured it'd be good karma to save other people that same headache!
 
Gravatar
# re: Automated installer version numbers for WiX (Brent @ 5/12/2009 5:21 PM)

Very handy. Thanks Sam!
 
Gravatar
# re: Automated installer version numbers for WiX (Scott @ 6/10/2009 11:52 AM)

Now, how to do this for those old VB6 exe files?
 
Gravatar
# re: Automated installer version numbers for WiX (Agustin @ 6/11/2009 5:26 AM)

Thanks! your post was really useful!
 
Gravatar
# re: Automated installer version numbers for WiX (Martin Rothschink @ 6/23/2009 7:05 PM)

A totally other solution to these kind of problems is the use of FinalBuilder. This is one of those absolutely essential tools. FinalBulder has many build in actions to do such things. I can't live without it. Have a look at www.finalbuilder.com
 
Gravatar
# re: Automated installer version numbers for WiX (Peter Ravnholt @ 7/3/2009 3:41 AM)

This was just the solution I was looking for, thank you!

One note: If you change

<GetAssemblyIdentity AssemblyFiles="..\HomeServerConsoleTab.DiskMgt\bin\Release\HomeServerConsoleTab.DiskMgt.dll">

to

<GetAssemblyIdentity AssemblyFiles="..\HomeServerConsoleTab.DiskMgt\bin\($Configuration)\HomeServerConsoleTab.DiskMgt.dll">

in your wix project file, it will be more robust.
 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 7/3/2009 8:06 AM)

Thanks Peter, great tip!

 
Gravatar
# re: Automated installer version numbers for WiX (Sandro Rudin @ 7/24/2009 9:03 AM)

Have you ever tried to run an upgrade of your setup? When I try that, I get a second installation instead of an update. The reason is simple: The Msi-Installer only looks at the first three positions in the version number (see documentation) thus ignoring any changes in the build number. Example: You define your assembly version as "1.2.3.*" -> your setup receives version "1.2.3.1111". You build again, setup receives version "1.2.3.1112". Great, but the installer ignores this change and does not perform any uninstall actions; so you have to manually change the third position, making this whole process useless. Am I missing something very basic here or am I just the first one who actually tried to run an update?
 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 7/24/2009 9:22 AM)

Hi Sandro,

This installer was built for Windows Home Server add-ins, which doesn't do upgrades.

However, your Visual Studio auto-versioning plugin should be able to increment the 3rd position as well as (or instead of) the 4th position. The plugin I linked to at the top of the post can do this.
 
Gravatar
# re: Automated installer version numbers for WiX (Sandro Rudin @ 7/24/2009 10:19 AM)

Thanks for the quick reply!
Yes, there are different ways how to update only the third position, but I wanted to use the !(bind.FileVersion.xxx) reference. Meanwhile I found that I have not been the first one to run an update ;-) and there are a few interesting discussions around, one of them being www.mail-archive.com/.../msg30501.html. The suggestion there is to update regardless of the version number which does the job for me.
 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 7/24/2009 10:44 AM)

Hm, maybe I misunderstood your question then.

When you use !(bind.FileVersion.FileId), and update the 3rd position using a Visual Studio plugin on each build, that doesn't trigger an upgrade when you install the MSI?

FileVersion should grab the whole version number, not just the 4th position.

 
Gravatar
# re: Automated installer version numbers for WiX (Sandro Rudin @ 7/24/2009 11:05 AM)

No, you're right, updating the third position does work; but I DON'T want to update the third position (because we already have a plugin running on our build servers that updates only the fourth position)...

Thanks for your responses, its working now...
 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 7/24/2009 11:08 AM)

Ah, that makes sense. Thanks for letting us know how you fixed it.

 
Gravatar
# re: Automated installer version numbers for WiX (Barry @ 10/24/2009 12:59 PM)

Thank you for this article...

I would like to use your technique for changing the name of the MSI file based on the current build/version as in the section above called "Automatic installer file names in a WiX project". However, I have no .NeT assemblies from which to grab said version number. I do have files, of course, and those files have the version number, but I am totally unfamiliar with AfterBuild processing in a wixproj file and would prefer to avoid a whole new career looking into that .... so could you please either give me an example of how to extract the version from a plain ol' file, or point me in the right direction. Many thanks in advance for your time.
 
Gravatar
# re: Automated installer version numbers for WiX (Dan @ 10/30/2009 5:33 PM)

Thanks a lot!! This made my life so much easier

I was wondering if you knew of a way, besides writing a custom task, to get the version without the revision number---like x.x.x?

I'm using this to write the version number into the desktop shortcut, and my users complain the revision number is distracting.
I couldn't find anything for doing a substring or regex on a variable within wix...
 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 10/30/2009 6:18 PM)

Hi Dan,

You'll need to download MSBuildTasks (community created extensions for MSBuild), and then you'll have access to Regex matching etc. See: social.msdn.microsoft.com/.../ed23dd39-79ad-41a...

 
Gravatar
# re: Automated installer version numbers for WiX (Sam Wood @ 10/30/2009 6:22 PM)

Hi Barry,

I haven't looked at grabbing parts of file names specifically, but I believe you'll be able to do what you need with some Regex magic based on the file name (see above regarding MSBuildTasks).

 

 
Gravatar
# re: Automated installer version numbers for WiX (Ryan @ 3/31/2010 12:11 PM)

Does binding work with WIX 2.0?

<Wix xmlns="schemas.microsoft.com/wix/2003/01/wi">

I didn't have any compiler errors however when I installed my program there were several errors because it does not accept non numeric values for VersionMajor and VersionMinor registry values.

When I checked the program version # in Programs & Features the Version says
"!(bind.assemblyFileVersion.MyFileWixId)".
 
Gravatar
# re: Automated installer version numbers for WiX (Stiefel @ 2/25/2011 3:35 AM)

Thank you Sam.

Two bits from me for other readers trying this:

1) Make sure you increase the 3rd position in your version number and not just the 4th.

2) Make sure your product-id is id="*"
 
Gravatar
# re: Automated installer version numbers for WiX (Andre @ 10/10/2011 3:42 PM)

awesome works well.
 
Gravatar
# re: Automated installer version numbers for WiX (Shikhar Jain @ 11/16/2011 2:20 AM)

Hi, Thanks alot.
This post gave me exactly what I was trying to implement.

Great work.

Post Comment

Title *
Name *
Email
Url
Comment *  
Remember me
Please add 6 and 8 and type the answer here:

Search

Site Sections

Recent Posts

Archives

Post Categories

WHS Add-In Tutorial

WHS Blogs

WHS Development