1. Create a new project in TFS
2. Automatic incrementation of the build number
3. Name the output directory using version number
4. Build deprecated Setup Projects (.vdproj) with TFS 2013
5. Build preconfigured ClickOnce packages with TFS for multiples environments
6. Build WebDeploy package with TFS for multiples environments

What we want to do ?

It’s easy to have a build number based on the current datetime that generates number like “20170602-15:33”. In this case you always will have a unique number but this is not comptaible with an assembler version number formatted such as “”.

According to the MSDN, here a short description of each part of the default version number:

Major Assemblies with the same name but different major versions are not interchangeable. A higher version number might indicate a major rewrite of a product where backward compatibility cannot be assumed.
Minor If the name and major version number on two assemblies are the same, but the minor version number is different, this indicates significant enhancement with the intention of backward compatibility. This higher minor version number might indicate a point release of a product or a fully backward-compatible new version of a product.
Build A difference in build number represents a recompilation of the same source. Different build numbers might be used when the processor, platform, or compiler changes.
Revision Assemblies with the same name, major, and minor version numbers but different revisions are intended to be fully interchangeable. A higher revision number might be used in a build that fixes a security hole in a previously released assembly.


In my company, we define a version number like this:

Major Changed for each big evolution, an important update or redraw
Minor Add a feature, a view, …
HotFix Fix an issue without improvements
Build Build number incremented automatically by our build server


So we can we can distinguish 2 steps: 
1. Update the name of the current build
2. Get the current version number from SharedAssembly file, increment it then save changes directly in TFS

 How to implement a custom version number?

The way I used to implement this custom behavior is to write a custom activity that could be integared easily in the XAML workflow.

I found a very useful article here: https://msdn.microsoft.com/en-us/library/hh850441(v=vs.120).aspx that explains in details how to create a new activity.

Update the name of the current build

I created an activity named “IntegrateVersionInBuildNameActivity” that manages this action.

First we need to get the assembly version. Like I said in the first article of this series, I have a single file called “SharedAssembly” in the project solution items. This file is referenced by every projects of my solution and must define at least the following properties:

[assembly: AssemblyVersion("")]
[assembly: AssemblyFileVersion("")]


public sealed class GetAssemblyVersion : CodeActivity<string>
    public InArgument<string> AssemblyInfoFileMask { get; set; }
    public InArgument<IBuildDetail> BuildDetail { get; set; }
    public InArgument<bool> AutoIncrementVersionNumber { get; set; }
    protected override string Execute(CodeActivityContext context)
        // Obtain the runtime value of the input arguments
        string assemblyInfoFileMask = context.GetValue(this.AssemblyInfoFileMask);
        IBuildDetail buildDetail = context.GetValue(this.BuildDetail);
        var workspace = buildDetail.BuildDefinition.Workspace;
        var vc = buildDetail.BuildServer.TeamProjectCollection.GetService<VersionControlServer>();
        string attribute = "AssemblyFileVersion";
        // Define the regular expression to find (which is for example 'AssemblyFileVersion("")' )
        Regex regex = new Regex(attribute + @"\(""\d+\.\d+\.\d+\.\d+""\)");
        // For every workspace folder (mapping)
        foreach (var folder in workspace.Mappings)
            // Get all files (recursively) that apply to the file mask
            ItemSet itemSet = vc.GetItems(folder.ServerItem + "//" + assemblyInfoFileMask, RecursionType.Full);
            foreach (Item item in itemSet.Items)
                context.TrackBuildMessage(string.Format("Download {0}", item.ServerItem), BuildMessageImportance.High);
                // Download the file
                string localFile = Path.GetTempFileName();
                // Read the text from the AssemblyInfo file
                string text = File.ReadAllText(localFile);
                // Search for the first occurrence of the version attribute
                Match match = regex.Match(text);
                // When found
                if (match.Success)
                    // Retrieve the version number 
                    string versionNumber = match.Value.Substring(attribute.Length + 2, match.Value.Length - attribute.Length - 4);
                    Version version = new Version(versionNumber);
                    Version newVersion = version;
                    if (context.GetValue(AutoIncrementVersionNumber) == true)
                        // Increase the build number -> this will be the new version number for the build
                        newVersion = new Version(version.Major, version.Minor, version.Build + 1, version.Revision);
                    context.TrackBuildMessage(string.Format("Version found {0}", newVersion), BuildMessageImportance.High);
                    return newVersion.ToString();
        return "No version found";


Get version number from the project’s file “SharedAssembly.cs” then save the new value in TFS


Last modified: 6 February 2018



Write a Reply or Comment

Your email address will not be published.