For the full context and guidance on how to develop and implement a custom activity in Team Build see the Microsoft Visual Studio Rangers Team Foundation Build Customization Guide V.1 at http://vsarbuildguide.codeplex.com/ There are many ways to stamp or set the version number of your assemblies. This approach is based on the build number. namespace CustomActivities
{
using System;
using System.Activities;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Build.Client;
[BuildActivity(HostEnvironmentOption.Agent)]
public sealed class VersionAssemblies : CodeActivity
{
/// <summary>
/// AssemblyInfoFileMask
/// </summary>
[RequiredArgument]
public InArgument<string> AssemblyInfoFileMask { get; set; }
/// <summary>
/// SourcesDirectory
/// </summary>
[RequiredArgument]
public InArgument<string> SourcesDirectory { get; set; }
/// <summary>
/// BuildNumber
/// </summary>
[RequiredArgument]
public InArgument<string> BuildNumber { get; set; }
/// <summary>
/// BuildDirectory
/// </summary>
[RequiredArgument]
public InArgument<string> BuildDirectory { get; set; }
/// <summary>
/// Publishes field values to the build report
/// </summary>
public OutArgument<string> DiagnosticTextOut { get; set; }
// If your activity returns a value, derive from CodeActivity<TResult> and return the value from the Execute method.
protected override void Execute(CodeActivityContext context)
{
// Obtain the runtime value of the input arguments
string sourcesDirectory = context.GetValue(this.SourcesDirectory);
string assemblyInfoFileMask = context.GetValue(this.AssemblyInfoFileMask);
string buildNumber = context.GetValue(this.BuildNumber);
string buildDirectory = context.GetValue(this.BuildDirectory);
// ** Determine the version number values **
// Note: the format used here is: major.secondary.maintenance.build
// -----------------------------------------------------------------
// Obtain the build definition name
int nameStart = buildDirectory.LastIndexOf(@"\") + 1;
string buildDefinitionName = buildDirectory.Substring(nameStart);
// Set the primary.secondary.maintenance values
// NOTE: these are hard coded in this example, but could be sourced from a file or parsed from a build definition name that includes them
string p = "1";
string s = "5";
string m = "2";
// Initialize the build number
string b;
string na = "0"; // used for Assembly and Product Version instead of build number (see versioning best practices: **TBD reference)
// Set qualifying product version information
string productInfo = "RC2";
// Obtain the build increment number from the build number
// NOTE: this code assumes the default build definition name format
int buildIncrementNumberDelimterIndex = buildNumber.LastIndexOf(".");
b = buildNumber.Substring(buildIncrementNumberDelimterIndex + 1);
// Convert version to integer values
int pVer = Convert.ToInt16(p);
int sVer = Convert.ToInt16(s);
int mVer = Convert.ToInt16(m);
int bNum = Convert.ToInt16(b);
int naNum = Convert.ToInt16(na);
// ** Get all AssemblyInfo files and stamp them **
// Note: the mapping of AssemblyInfo.cs attributes to assembly display properties are as follows:
// - AssemblyVersion = Assembly Version - used for the assembly version (does not change unless p, s or m values are changed)
// - AssemblyFileVersion = File Version - used for the file version (changes with every build)
// - AssemblyInformationalVersion = Product Version - used for the product version (can include additional version information)
// ------------------------------------------------------------------------------------------------------------------------------------------------
Version assemblyVersion = new Version(pVer, sVer, mVer, naNum);
Version newAssemblyFileVersion = new Version(pVer, sVer, mVer, bNum);
Version productVersion = new Version(pVer, sVer, mVer);
// Setup diagnostic fields
int numberOfReplacements = 0;
string addedAssemblyInformationalAttribute = "No";
// Enumerate over the assemblyInfo version attributes
foreach (string attribute in new[] { "AssemblyVersion", "AssemblyFileVersion", "AssemblyInformationalVersion" })
{
// Define the regular expression to find in each and every Assemblyinfo.cs files (which is for example 'AssemblyVersion("1.0.0.0")' )
Regex regex = new Regex(attribute + @"\(""\d+\.\d+\.\d+\.\d+""\)");
foreach (string file in Directory.EnumerateFiles(sourcesDirectory, assemblyInfoFileMask, SearchOption.AllDirectories))
{
string text = File.ReadAllText(file); // Read the text from the AssemblyInfo file
// If the AsemblyInformationalVersion attribute is not in the file, add it as the last line of the file
// Note: by default the AssemblyInfo.cs files will not contain the AssemblyInformationalVersion attribute
if (!text.Contains("[assembly: AssemblyInformationalVersion(\""))
{
string lastLine = Environment.NewLine + "[assembly: AssemblyInformationalVersion(\"1.0.0.0\")]";
text = text + lastLine;
addedAssemblyInformationalAttribute = "Yes";
}
// Search for the expression
Match match = regex.Match(text);
if (match.Success)
{
// Get file attributes
FileAttributes fileAttributes = File.GetAttributes(file);
// Set file to read only
File.SetAttributes(file, fileAttributes & ~FileAttributes.ReadOnly);
// Insert AssemblyInformationalVersion attribute into the file text if does not already exist
string newText = string.Empty;
if (attribute == "AssemblyVersion")
{
newText = regex.Replace(text, attribute + "(\"" + assemblyVersion + "\")");
numberOfReplacements++;
}
if (attribute == "AssemblyFileVersion")
{
newText = regex.Replace(text, attribute + "(\"" + newAssemblyFileVersion + "\")");
numberOfReplacements++;
}
if (attribute == "AssemblyInformationalVersion")
{
newText = regex.Replace(text, attribute + "(\"" + productVersion + " " + productInfo + "\")");
numberOfReplacements++;
}
// Publish diagnostics to build report (diagnostic verbosity only)
context.SetValue(this.DiagnosticTextOut, " Added AssemblyInformational Attribute: " + addedAssemblyInformationalAttribute +
" Number of replacements: " + numberOfReplacements +
" Build number: " + buildNumber +
" Build directory: " + buildDirectory +
" Build definition name: " + buildDefinitionName +
" Assembly version: " + assemblyVersion +
" New file version: " + newAssemblyFileVersion +
" Product version: " + productVersion +
" AssemblyInfo.cs Text Last Stamped: " + newText);
// Write the new text in the AssemblyInfo file
File.WriteAllText(file, newText);
// restore the file's original attributes
File.SetAttributes(file, fileAttributes);
}
}
}
}
}
}