I am currently enjoying the wealth of new Visual Studio 2012 features. It was a few days before I really appreciated the new user experience, since productivity and access to common options are much improved. This is not the focus of this article, but I thought it was worth mentioning. This post is about sharing and saving time.

The TFS 2012 default XAML build template does not provide support for versioning, which is a feature that provides injecting assembly version and build information. This information is critical to validate a deployment by checking the assemblies and collecting the unique version number. This value is a combination of the major version, minor version, build number and revision. You can view the version information by selecting the assembly file properties under the details tab.

Assembly File Properties

The project AssemblyInfo file maintains the values for the version information. The AssemblyFileVersionAttribute contains a build number, so this information should be changed during every build. In this scenario, the AssemblyFileVersionAttribute should be associated with a specific TFS build. This can be accomplished by customizing the default build template to include a process to assign a unique version number linked to the build.

The first step is create a copy of the default XAML build template and add to source control. You can rename this file, since it will be a custom XAML template. Next, download the Community TFS Build Extensions from CodePlex, which contains a collection of code activities to extend the current core functionality. This includes the TfsVersion activity, which is a versioning task supporting the assignment and assembly file injection of the information. You must add the Community TFS Build Extension assemblies to source control and reference the custom assemblies with the TFS Build Controller.

The following are the modifications required, so change the new XAML build template created earlier. It is easier to create a new TFSBuild project, add the assembly references and link (i.e. not add to the project) to the XAML build template. If you do not setup a project then editing the XAML is difficult without the activities appearing in the Toolbox. 

Add the Major, Minor and TFSVersionNumber arguments to the build template.

Build Template Arguments

Click the Metadata arguments selection and add the Major, Minor and TFSVersion parameters below, so the build definition will provide help and categorized information.

Build Template Metadata Major

Build Template Metadata Minor

Build Template Metadata TFSVersionNumber

The TFSVersionNumber is only available when queuing a build, so it will not appear in the build definition. This provides the option to override the generated version number when manually triggering a build. This will be handled with a conditional, so if the value is set then skip generating a version number. The Major and Minor parameters are assigned with the build definition or queuing a manual build. The three parameters will be grouped under the Versioning category, so they will be easier to manage.

Next, add the build template items to assign the version number.

Build Template SetVersionNumber

The new activities must appear within the current Update Build Number For Triggered Builds, so the build number/name is assigned the same value as the assembly information. If the TFSVersionNumber is not set then SetVersionNumber conditional executes GetTFSVersion to assign the value for the build. The GetTFSVersion properties appear below, which generates the version number based on the Major and Minor values. The unique build number is assigned as the 3rd element of the version number, which are all separated by a delimiter.

Build Template GetTfsVersion Properties

The Action property is set to GetVersion, so the generated version number is assigned to the TFSVersionNumber. It is assigned as the build number and file version in subsequent tasks.

Build Template GetTfsVersion Properties Version

The current Update Build Number is changed to assign the TFSVersionNumber, so the build number is the same value as the version number. I recommend appending the build definition name, so the following is an example.

  • MyBuildDefinition_2.1.167.01

The final step is the file versioning, where the version number is injected into the AssemblyInfo files before compiling. The following is the build template with the new items.

ild Template ApplyVersionNumber

The Apply FileVersionNumber appears after the current Get Workspace, which contains a condition to verify the TFSVersionNumber is assigned. The TFSFileVersioning sequence includes FileMatchingAssemblyInfo and SetTfsVersion. The FileMatchingAssemblyInfo properties appear below, which basically generates a list of AssemblyInfo files from the current workspace.

Build Template SetVersionNumber FindingMatchingFiles

The SetTfsFileVersioning properties appear in the next image, which accept the AssemblyFiles collection and TFSVersionNumber.

Build Template SetVersionNumber Properties

The TfsVersion activity is again handling the work, but in this case injecting the previously generated version number into the AssemblyInfo files.

After almost committing to building custom activities to perform the same tasks, I stumbled onto the TFS Community Build Extensions and the very helpful TfsVersion activity. After a few more hours of testing the various options, I arrived at the above process. In my case, synchronizing the build number and AssemblyFileVersion was the objective. If you seek a slightly different process then I would look at the TFS Community Build Extensions and the TfsVersion activity options.

In the end, I hope this saves you a little time and research. If you find something helpful then please comment and share.