The other day I wrote about how to incorporate build numbers into your .CSPROJ and .VCXPROJ files. In doing some more testing I found in some edge cases where the way I was getting the current build number by including Microsoft.TeamFoundation.Build.targets could interfere with the TFS Build. That’s not good so I fixed the problem by declaring and using the GetBuildProperties task by itself. That avoids the odd build case and makes everything work. I’ve updated the sample with the latest Wintellect.TFSBuildNumber.targets file so grab it here.

In my previous post I showed the simple example of changing the one .CSPROJ or .VCXPROJ file that’s built at the beginning of your build. I was working on a large system that was broken into multiple .SLN files that could be built in any order. That meant I had to edit multiple projects and wanted to show how I simplified the integration into many projects.

First I created a common ,Targets file I called VersionNumbers.Targets that included everything necessary for creating the version number files for both C# and C++ projects. The comments in the file explain what’s going on. You can use this file as the basis of all your version number files.

Version Numbers.Targets
  1. <Project xmlns="">
  3.   <PropertyGroup>
  4.     <!– The following two properties are mandatory with
  5.          Wintellect.TFSBuildNumber.targets–>
  6.     <TFSMajorBuildNumber>5</TFSMajorBuildNumber>
  7.     <TFSMinorBuildNumber>0</TFSMinorBuildNumber>
  8.   </PropertyGroup>
  10.   <!– Assume the shared directory but allow it to be changed before
  11.        before including this file. –>
  12.   <PropertyGroup Condition=" '$(SharedVersionOutputDirectory)' == '' ">
  13.     <SharedVersionOutputDirectory>..\Shared</SharedVersionOutputDirectory>
  14.   </PropertyGroup>
  16.   <!– Include the targets that create the version number files. –>
  17.   <Import Project="Wintellect.TFSBuildNumber.targets" />
  19.   <!– C# and VB projects are easy, I'll just jam in the file creation on the included
  20.       BeforeBuild which will get everything hooked up perfectly. –>
  21.   <Target Name="BeforeBuild"
  22.         DependsOnTargets="WriteSharedTextAssemblyVersionFile;
  23.                           WriteSharedCSharpAssemblyVersionFile;
  24.                           WriteSharedCPPAssemblyVersionFile;
  25.                           WriteSharedWiXAssemblyVersionFile;"
  26.           Condition="('$(MSBuildProjectExtension)' == '.csproj') Or ('$(MSBuildProjectExtension)' == '.vbproj')">
  27.   </Target>
  29.   <!– Only use the named target if it's a C++ build, otherwise you get an MSBuild
  30.        warning MSB4057 about an non existant target. –>
  31.   <PropertyGroup Condition=" '$(MSBuildProjectExtension)' == '.vcxproj' ">
  32.     <CppResourceCompile>ResourceCompile</CppResourceCompile>
  33.   </PropertyGroup>
  35.   <!– For C++ projects, jam in the file creation before doing the Resource Compiler
  36.        build. –>
  37.   <Target Condition=" '$(MSBuildProjectExtension)' == '.vcxproj' "
  38.           Name="BuildVersionFiles"
  39.           BeforeTargets="$(CppResourceCompile)"
  40.           DependsOnTargets="WriteSharedTextAssemblyVersionFile;
  41.                             WriteSharedCSharpAssemblyVersionFile;
  42.                             WriteSharedCPPAssemblyVersionFile;
  43.                             WriteSharedWiXAssemblyVersionFile;">
  44.   </Target>
  46. </Project>

Once everything is isolated into your VersionNumber.Targets file, you can include it with the following line in your .CSPROJ or .VCXPROJ file.

Import Example
  1. <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  2. <Import Project="..\Build\VersionNumbers.Targets"/>