Skip to content


Subversion checkout URL

You can clone with
Download ZIP
An MSBuild integration for shared versioning across all projects in a solution, where user supplies Major / Minor and Build / Revision are calculated by date/time and other DVCS properties make their way into the assembly metadata.

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.



CroMag helps to version all of the projects within a solution via a single file convention, and will bump build and version numbers of your project automatically during the build based on a date and version number scheme AND a build number variable that can originate from a build server like Jenkins. Furthermore, DVCS changeset hashes also make their way into built assemblies.


  • Nuget
  • Package restore via PepitaGet (or Nuget) highly recommended
  • MSBuild 4 or higher (uses static property functions)
  • To have the current short SHA1 hash added to AssemblyConfiguration, you must be using Mercurial or Git

What does it do?

CroMagVersion allows projects to share the following assembly attributes:

  • AssemblyCompany - Uses $(VersionCompany) and $(VersionCompanyUrl) from version.props
  • AssemblyCopyright - Copyright $(Year) $(VersionCompany) from version.props
  • AssemblyConfiguration - Annotated with build Configuration (i.e. Debug, Release) and the SHA1 hash of the current source version

  • AssemblyVersion - Calculates date convention based version

  • AssemblyFileVersion - Calculates date convention based version by default, but the layout can be customized (see below)
  • AssemblyInformationalVersion - Calculates date convention based version, but the layout can be customized (see below)

How does it work?

  • During the package installation SharedAssemblyInfo.cs is added to the project file as a linked file. This file will be shared amongst all projects that install the package, and not actually copied into any projects.

  • A new msbuild file called version.props is copied to the solution folder if it doesn't exist - this is where user modifications such as major and minor version should be made. These values are configurable and should always be modified by hand as needed. If following semantic guidelines, there's no easy way to identify what things are breaking changes - this requires a human of at least average intelligence.

<!-- Typically this value will be supplied by a build server like Jenkins -->
  • A CroMagVersion.targets file is injected into the project as an Import that contains the version update code

  • Before the build goes down, SharedAssemblyInfo.cs file is updated with the major / minor version from version.props and has date based version information added in the following format: $(MajorVersion).$(MinorVersion).$(YearMonth).$(DayNumber)$(Build)

    • YearMonth is a 2 digit year, 2 digit month - for instance 1203
    • DayNumber is a 2 digit day - for instance 03 or 31
    • $(Build) is 0 by default, or BUILD_NUMBER environment variable as supplied by Jenkins or via an override in version.props. Only the last 3 digits of this number can be used, as each fragment of the build number has a maximum of 65536.

Is this the best way to date tag a build? Not necessarily, but it's a pretty reasonable solution that results in something human readable after the fact.

Customizing The Layout

AssemblyFileVersion and AssemblyInformationalVersion can have customized layouts by enabling AssemblyFileVersionLayout or AssemblyInformationalVersionLayout in version.props . This may be necessary to deal with wacky installers (like MSI) that don't consider a bump to the 4th number significant enough to upgrade an existing product install. Sigh...

The following is pretty self-explanatory:

<!-- Available variables for a custom layout are:
    $(MajorVersion) - from this file
    $(MinorVersion) - from this file
    $(BUILD_NUMBER) - original number from build server / environment variable if available, otherwise 0, unless overriden in this file
    $(Build) - BUILD_NUMBER truncated to last 3 digits
    $(YearMonth) - yyMM
    $(DayNumber) - dd
    $(Year) - yyyy

    $(BuildVersion) - $(YearMonth)
    $(RevisionVersion) - $(DayNumber)$(Build)

    $(VersionNumber) - $(MajorVersion).$(MinorVersion).$(BuildVersion).$(RevisionVersion)

    Note that these are NOT proper MSBuild variables, and therefore
    arbitrary variables will not resolve.  Only these whitelisted
    variables will do anything.  All other strings, valid or not,
    will be treated as plaintext.


A note about naming conventions for version pieces

This project follows the standard .NET style naming convention specified by System.Version of Major.Minor.Build.Revision, where the 3rd and 4th numbers are Build and Revision.

Other systems tend to use different schemes:

  • Major.Minor.Revision.Build - common many places, including, Java
  • Major.Minor.Patch - for instance SemVer
  • Major.Minor.Build, for instance MSI ProductVersion.

The names for the slots aren't important so much as the semantics.

Similar Projects

  • SemVerHarvester - MSBuild task library that harvests version numbers from tags in source control versions. It appears to work with both Git and Mercurial.

Future Improvements

  • Ensure Mono works properly


Fork the code, and submit a pull request!

Any useful changes are welcomed. If you have an idea you'd like to see implemented that strays far from the simple spirit of the application, ping us first so that we're on the same page.


Something went wrong with that request. Please try again.