Klee
Klee

Reputation: 2032

Getting Project Version Information During MSbuild build

I'm attempting to automate the building of our installers through MSBuild. The problem that I have come up against is getting the Version information of the C# project which is calling the custom MSBuild script, which would then pass the version number into Wix during the build process.

What I would like to do is to set the version into some properties like this:

<ProductVersion>$(MajorVersion).$(MinorVersion).$(PatchVersion).$(BuildVersion)</ProductVersion>
<InstallerName>"$(ProductName)-$(ProductVersion).msi"</InstallerName>

The version is updated as part of our continuous integration build and incorporating the version number into each installer that is built on our continuous integration server helps us in producing an application that is Continuously Deployable.

Any help would be greatly appreciated.

Upvotes: 3

Views: 2301

Answers (1)

Petrik
Petrik

Reputation: 1981

The way I have solved this problem is by creating a 'version.xml' file in my code repository. This file contains the following data

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5"
         DefaultTargets="Build"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <VersionMajor>0</VersionMajor>
        <VersionMinor>1</VersionMinor>
        <VersionBuild>1</VersionBuild>
        <VersionRevision>0</VersionRevision>
    </PropertyGroup>
</Project>

In my case this file is checked in but it should not be too hard to generate this file with information from the build server or whatever is desired.

During the build a custom MsBuild taks (similar to the TemplateFile task) creates an assembly info file and a Wix include file from their respective template files. The 'version.xml' file is accessed by including it in the MsBuild script. For example like this:

<?xml version="1.0" encoding="utf-8"?>
<Project 
    ToolsVersion="4.0" 
    DefaultTargets="Build" 
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <!-- Include the version info file so that we can pull the version info from it -->
    <Import 
        Project="$(DirWorkspace)\version.xml" 
        Condition="Exists('$(DirWorkspace)\version.xml')" />

    <!-- Generate a file with the version information -->
    <Target Name="GenerateAssemblyInfoVersionNumber">
    <ItemGroup>
      <VersionTokens Include="Major">
        <ReplacementValue>$(VersionMajor)</ReplacementValue>
      </VersionTokens>
      <VersionTokens Include="Minor">
        <ReplacementValue>$(VersionMinor)</ReplacementValue>
      </VersionTokens>
      <VersionTokens Include="Build">
        <ReplacementValue>$(VersionBuild)</ReplacementValue>
      </VersionTokens>
      <VersionTokens Include="Revision">
        <ReplacementValue>$(VersionRevision)</ReplacementValue>
      </VersionTokens>
    </ItemGroup>
    <TemplateFile 
        Template="$(FileTemplateAssemblyVersion)"
        OutputFileName="$(FileGeneratedAssemblyVersion)" 
        Tokens="@(VersionTokens)" />
  </Target>
</Project>

The AssemblyInfo.VersionNumber.cs file which is included in the C# projects is generated from a template file that looks like:

//-----------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost
//     if the code is regenerated.
// </auto-generated>
//-----------------------------------------------------------------------

using System.Reflection;

[assembly: AssemblyVersion("${Major}.${Minor}.${Build}.${Revision}")]
[assembly: AssemblyFileVersion("${Major}.${Minor}.${Build}.${Revision}")]

// The AssemblyInformationalVersion stores the version that will be displayed in
// Windows explorer.
[assembly: AssemblyInformationalVersion("${Major}.${Minor}.${Build}.${Revision}")]

During the replacement process the ${TEXT_HERE} sections are replaced with their respective values.

The Wix include template file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <!--
      This is a generated file.
      Do NOT make changes to this file.
      They will be undone next time the file is generated.
    -->

    <!-- The current version -->
    <?define CurrentVersion = "${Major}.${Minor}.${Build}"?>

    <!-- The install version string -->
    <?define ProductVersionFolder = "${Major}.${Minor}"?>
</Include>

After including this file it is possible to refer to the CurrentVersion and the ProductVersionFolder variables in the Wix installer where ever it is needed.

By using this method the version information is stored in a single location and can be accessed by all parts of the build.

Upvotes: 2

Related Questions