Last week I came up with a fancy requirement that forced me to struggle a little bit in order to find an appropriate solution. Let’s say that we have a massive solution file, containing something like 100ish projects and we would like to keep the same assembly version number for all these projects.
In this article I will show you how the assembly version number works in .NET and what are the possible solutions, using Visual Studio.
Assembly version in .NET
As soon as you add a new project (of any type) in Visual Studio 2010, you will come up with a default template that contains also a file “AssemblyInfo.cs” if you are working with C# or “AssemblyInfo.vb” if you are working with VB.NET.
If we look at the content of this file we will discover that it contains a set of attributes used by MSBuild to prepare the assembly file (.dll or .EXE) with the information provided in this file. In order to change this information we have two options:
- Edit the AssemblyInfo.cs using the Visual Studio editor.
In this case we are interested in the following attributes, that we will need to change every time we want to increase the assembly version number:
1: using System.Reflection;
2: using System.Runtime.CompilerServices;
3: using System.Runtime.InteropServices;
5: [assembly: AssemblyVersion("220.127.116.11")]
6: [assembly: AssemblyFileVersion("18.104.22.168")]
- Or, we can open the Project properties window from Visual Studio using the shortcut ALT+ENTER or by choosing “properties” of a VS project file from the Solution Explorer
How does the versioning work?
The first thing that I tried was to understand exactly how this magic number works in .NET.
If you go to the online MSDN article, you will find out that the version number of an assembly is composed by 4 numbers, and each one has a specific mean
1. Major = manually incremented for major releases, such as adding many new features to the solution.
0. Minor = manually incremented for minor releases, such as introducing small changes to existing features.
0. Build = typically incremented automatically as part of every build performed on the Build Server. This allows each build to be tracked and tested.
0 Revision = incremented for QFEs (a.k.a. “hotfixes” or patches) to builds released into the Production environment (PROD). This is set to zero for the initial release of any major/minor version of the solution.
Two different assembly version attributes, why?
I noticed that the [assembly] attribute class exposes two different properties, Assembly Version and Assembly File Version.
This attribute should be incremented every time our build server (TFS) runs a build. Based on the previous description you should increase the third number, the build version number. This attribute should be placed in a different .cs file for each project to allow full control of it.
This attributes represents the version of the NET assembly you are referencing in your projects. If you increase this number in every TFS build, you will incur in the problem of changing your reference redirect every time the assembly version is increased.
This number should be increased only when you release a new version of your assembly and it should be increase following the assembly versioning terminology (major, minor, …)
Control the Versioning in Visual Studio
As I said before VS allows us to control the version number in different ways and in my opinion using the properties window is the easiest one. As soon as you change one of the version numbers from the properties window, also the AssembliInfo.cs file will be automatically changed.
But what happens if we delete the version attributes from the assembly info file? As expected VS will create an assembly with version 0.0.0.0 like the picture below:
Sharing a common Assembly version on multiple projects
Going back to the request I got, how can we setup a configuration in Visual Studio that allows us to share on multiple projects the same assembly version? A partial solution can be accomplished using shared linked files on Visual Studio.
Ok, what’s a shared linked file, first of all? A linked file is a file shortcut that points in multiple projects to the same single file instance. A detailed explanation of this mechanism is available on Jeremy Jameson’s blog at this page.
Now, this is the solution I have created as an example where I share an AssemblyVersion.cs file and an AssemblyFileVersion.cs file to the entire Visual Studio solution.
Using this approach we have one single place where we can edit the AssemblyFileVersion and the AssemblyVersion attributes. In order to accomplish this solution you need to perform the following steps:
- Delete the assembly version and the assembly file version attributes for all the existing AssemblyInfo.cs files
- Create in one project (the root project) a file called AssemblyFileVersion.cs containing only the attribute AssemblyFileVersion
- Create in one project (the root project) a file called AssemblyVersion.cs containing only the attribute AssenblyVersion
- Add as linked files these two files to all the existing projects
- Re-Build everything
Final note on Visual Studio properties window
Even if my root project has now two files with the attributes AssemblyFileVersion and AssemblyVersion, when I open the Visual Studio properties window, it tries to search for these attributes in the AssemblyInfo.cs file, and clearly, it can’t find them anymore, so it does not display anything:
If you add a value to these textboxes Visual Studio will re-create the two attributes in the AssemblyInfo.cs file without taking care of the two new files we have created and as soon as you try to compile the project you will receive this nice error:
So, in order to use this solution you need to keep in mind that you can’t edit the AssemblyFileVersion and the AssemblyVersion attributes from the VS properties window if they are not saved in the AssemblyInfo.cs file!
I believe that MS should change this in the next versions of Visual Studio.