2010-03-17

Embedding a TFS Build label in all assemblies

The default TFS build label does not have a xx.xx.xx.xx pattern, but looks like “MyBuild_20070418.1”. So we cant assign the value to the AssemblyVersion or AssemblyFileVersion attribute, however the AssemblyInformationalVersion attribute can be used as it is a string.

   1: <Target Name="AfterGet">
   2:   <!-- Insert build label into assemblies -->
   3:   <Message Text="Modifying AssemblyInfo files under &quot;$(SolutionRoot)&quot;." />
   4:  
   5:   <Message Text="Undo checkout assemblyinfo files, make sure no files are checked out." />
   6:   <Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe&quot; undo *.* /recursive /noprompt"
   7:         WorkingDirectory="$(MSBuildProjectDirectory)\..\sources" ContinueOnError="true"/>
   8:  
   9:   <Message Text="Checkout assemblyinfo files" />
  10:   <Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe&quot; checkout &quot;AssemblyInfo.*&quot; -r"
  11:         WorkingDirectory="$(MSBuildProjectDirectory)\..\sources" ContinueOnError="true"/>
  12:  
  13:   <ItemGroup>
  14:     <AssemblyInfoFilesCs Include="$(SolutionRoot)\**\assemblyinfo.cs" />
  15:   </ItemGroup>
  16:  
  17:   <Message Text="Adding $(LabelName) to %(AssemblyInfoFilesCs.fullpath)" />
  18:   
  19:   <WriteLinesToFile
  20:           File="%(AssemblyInfoFilesCs.fullpath)"
  21:           Lines="[assembly: AssemblyInformationalVersion(&quot;$(LabelName)&quot;)]"
  22:           Overwrite="false"/>
  23: </Target>
  24:  
  25:  
  26:  
  27: <Target Name="AfterCompileSolution">
  28:   <Message Text="Undo checkout assemblyinfo files" />
  29:  
  30:   <Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\tf.exe&quot; undo *.* /recursive /noprompt"
  31:         WorkingDirectory="$(MSBuildProjectDirectory)\..\sources" ContinueOnError="false"/>
  32: </Target>

With this in place all assemblies (dll, exe), will have a AssemblyInformationalVersion attribute with the label of the TFS Build. So it should be a no-brainer to trace a dll to a point in time in TFS Source Control. Just open the dll in reflector and disassemble the dll.

reflector

An alternative to AssemblyInformationalVersion  would be AssemblyConfiguration, but then we have to use a task that can do a text replace, as it is usually already defined in AssemblyInfo.cs files.

2 comments:

Jason Stangroome said...

Great work but it won't be ideal for all projects. For example, the AssemblyInformationalVersion is used for the Application.UserAppData* properties, effecting existing data when a user upgrades app versions.

It can also raise a compiler warning if the "M.m.b.r" format isn't used (which TFS Build Numbers generally don't) and if Treat Warnings As Errors in enabled, this could fail the build.

Regards,

Jason

Anonymous said...

Hi! Where do I have to put the XML code ...?