Marking Builds

One thing that I find strangely difficult and awkward to do, with little to no documentation anywhere on the internet that I can find, is how to automatically mark your built binaries with the specific version of source code from your revision control system that was used to build them. Seems like a pretty good idea to me - if you have your app loaded on a test system or a staging server or whatever, wouldn’t you like to have a way to check if it’s really the version that you think it is, besides checking on creation dates or typing MyApp-2-dave-test3.exe on the name or something? Yet all of my searches on this topic have found nothing, so I started working on something of my own.

I’m doing most of my work for this one in Visual Studio with .NET, and I am using Mercurial for most of my side projects at this time. Here’s what I’ve come up with for that:

In the Pre-build event command line field of your project, paste the following:

cd $(ProjectDir)
echo using System.Reflection; > Properties\HGVersion.cs
for /f "delims=" %%a in ('hg id -i') do @set b=%%a
echo [assembly: AssemblyInformationalVersion("%b%")] >> Properties\HGVersion.cs

Yes, that third line is apparently how you get the results from running a command into an environmental variable in batch scripts. Aren’t batch scripts fun? Anyways, this script will run hg id -i, resulting in the hash code for your current changeset, and uses it to generate a file HGVersion.cs in your project’s Properties directory that reads like this:

using System.Reflection; 
[assembly: AssemblyInformationalVersion("c2444e4fabfd")]

Build the project once to run the script, then add the resulting HGVersion.cs file to your project, and make sure you add it to your .hgignore file too. Now your exe or dll will have its Mercurial changeset in the Product version field that you can see in Properties in Windows Explorer. As far as I can tell, it’s not possible for the user to change that normally, so it should be a durable way to mark what version your executable is. You can also retrieve it within your application, for About boxes and such, with the following:

(Assembly.GetExecutingAssembly()
.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)
.First() as AssemblyInformationalVersionAttribute)
.InformationalVersion

I suppose you could also use this to check the build version of other assemblies that you’re using to prevent problems - it’s probably simpler than using strong names.

One other thing that’s handy about this is that builds made with uncommitted changes will have a + sign after their version - like c2444e4fabfd+. You can at least tell if the assembly was made with uncommitted changes, even though you can’t tell what they were easily.

Is everybody out there hacking together workarounds like this with command line scripts and such? If there’s a really good way out there to do this, somebody please let me know. Even TFS, which has its own build system and is tightly integrated into VS, doesn’t seem to have any way to do it.

Comments