Auto-increment build numbers in Visual Studio

You need to auto-increment your build numbers in order to easily tell which code you’re working with.

In this article I’ll explain how to auto-increment your build numbers in Visual Studio. I’ll be using text templating to generate the Assembly Version.

1 – Choose a versioning scheme

I’m going to be using the version scheme: <Major Version>.<Minor Version>.<Days Since Project Started>.<Minutes Since Midnight>. You should use whatever makes sense for you.

The one rule you must adhere to is the numbers must be <= 65534 (because they are 16-bit). If you generate a number greater than 65534, you’ll get a build error:

CS7034 The specified version string does not conform to the required format - major[.minor[.build[.revision]]]
Code language: plaintext (plaintext)

There are 86400 seconds per day and 1440 minutes per day. This is why I chose Minutes Since Midnight instead of Seconds Since Midnight. Since 86400 > the limit of 65534, using seconds would sometimes result in the build error shown above. By using minutes, this cannot happen.

2 – Comment out the assembly version properties

Open AssemblyInfo.cs and comment out AssemblyVersion and AssemblyFileVersion.

3 – Add a Text Template file

A Text Template is used to generate code. We’ll be using this to generate the assembly version.

After you add this file you’ll get a warning prompt. Since you’re the one adding this file, you can check the box and click OK.

4 – Update the Text Template to generate the AssemblyVersion property

There’s two parts to the text template:

  1. Specifying the template using placeholder variables.
  2. Populating the placeholder variables.
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #> using System.Reflection; [assembly: AssemblyVersion("<#= this.Major #>.<#= this.Minor #>.<#= this.DaysSinceProjectStarted #>.<#= this.MinutesSinceMidnight #>")] <#+ int Major = 1; int Minor = 0; static DateTime ProjectStartedDate = new DateTime(year: 2020, month: 3, day: 12); int DaysSinceProjectStarted = (int)((DateTime.UtcNow - ProjectStartedDate).TotalDays); int MinutesSinceMidnight = (int)DateTime.UtcNow.TimeOfDay.TotalMinutes; #>
Code language: C# (cs)

5 – Update .csproj to run the text template every time it builds

  1. Edit your .csproj in Notepad.
  2. Make two changes:
    • Import Microsoft.TextTempatings.targets.
    • Add the TransformOnBuild, OverwriteReadOnlyOutputFiles, and TransformOutOfDateOnly properties to each build configuration.

The .csproj below shows these highlighted changes:

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{221097A0-A3F4-45CC-A6C0-B13455C6EAFE}</ProjectGuid> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>AutoIncrementingBuild</RootNamespace> <AssemblyName>AutoIncrementingBuild</AssemblyName> <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <Deterministic>true</Deterministic> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <TransformOnBuild>true</TransformOnBuild> <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles> <TransformOutOfDateOnly>false</TransformOutOfDateOnly> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <TransformOnBuild>true</TransformOnBuild> <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles> <TransformOutOfDateOnly>false</TransformOutOfDateOnly> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> <Reference Include="System.Data" /> <Reference Include="System.Net.Http" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="VersionAutoIncrement.cs"> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> <DependentUpon>VersionAutoIncrement.tt</DependentUpon> </Compile> </ItemGroup> <ItemGroup> <Content Include="VersionAutoIncrement.tt"> <Generator>TextTemplatingFileGenerator</Generator> <LastGenOutput>VersionAutoIncrement.cs</LastGenOutput> </Content> </ItemGroup> <ItemGroup> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v16.0\TextTemplating\Microsoft.TextTemplating.targets" /> </Project>
Code language: HTML, XML (xml)

Note: This is specifically adding the VS2019 path.

6 – Build the project

When you build the project it’ll execute the text template. This generates a source file with the AssemblyVersion property.

6 thoughts on “Auto-increment build numbers in Visual Studio”

  1. To me, this is totally not working!
    Yes, the VersionAutoIncrementer.cs file is created, but it is stuck in its original version number.
    E.g. stuck in:

    using System.Reflection;
    [assembly: AssemblyVersion(“8.0.220.927”)]

    Reply
    • Hi Bjorn,

      Good catch. I updated the page to include instructions for how to update your .csproj file to make it run the text templating transform on every build.

      Please take a look at the step I added to the page – 5 – Update .csproj to run the text template every time it builds.

      Let me know if this helps.

      Reply
  2. I have created the template for shared assembly info.tt its updating version number only once for the first build or rebuild.
    If I change some code and try to build the whole project it’s not reflecting the version number.

    Reply
      • Hi Mak,
        Yes, I did. if I do changes related to that project then the revision number getting updated.if anything other than that project it’s not updating.

        Below is my code in SharedAssembyInfo.tt

        using System.Reflection;

        [assembly: AssemblyConfiguration(“”)]
        [assembly: AssemblyCompany(“GRIDSMART Technologies, Inc.”)]
        [assembly: AssemblyCopyright(“Copyright © GTI 2019”)]
        [assembly: AssemblyTrademark(“”)]
        [assembly: AssemblyCulture(“”)]
        [assembly: AssemblyVersion(“…”)]

        And followed all the steps included the below line in .csproj

        Reply
        • The text template only runs if the project is built. If there’s no changes in the project, then clicking “Build” in Visual Studio won’t build that project. Therefore it won’t run the text template.

          I’m not aware of a way to make “Build” build all projects, even if there are no changes.

          However, since it sounds like you want to run the text template every time, regardless of changes to the project, it really sounds like you want to use “Rebuild” instead of “Build” every time. That’s the simplest solution. There may be other ways to force VS to build your unchanged project, but “Rebuild” definitely makes it do that.

          Reply

Leave a Comment