Creating a custom check-in policy pack that works with multiple versions of Visual Studio.

Creating a custom check-in policy pack that works with multiple versions of Visual Studio.

Anyone who has ever tried to create a custom check-in policy for Visual Studio probably knows that the policy isn't specific to the TFS server version you're using, but to the version of Visual Studio that is connecting. This can be confusing for companies that are upgrading their Visual Studio, but not their TFS installation (or for people who've moved to Visual Studio Team Services).

You might be able to get away with using Binding Redirects in the Visual Studio .config file (and in the .config file of any other process that might invoke the policy) as documented here. This essentially tells .NET to load a newer version of a dependent assembly and will trick your policy that was created for an older version of Visual Studio to load in a newer one. You cannot use this trick to load a policy created for a newer version of Visual Studio in a older version.

The official way to resolve this, is to create a different binary for each Visual Studio Version and register that binary in the corresponding config hyve.

Each of these projects will be very similar and in many cases you can reuse the same .cs file for each version of Visual Studio (as long as you're not using any API that was introduced in a later version.

Step one, is to create the right projects:

| Visual Studio | Project Type | CPU | .NET Version | TFS OM Version | Visual Studio Version |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2017 | Class Library | AnyCPU | 4.6 | 15.0.0.0 | v15.0 |
| 2015 | Class Library | AnyCPU | 4.6 | 14.0.0.0 | v14.0 |
| 2013 | Class Library | AnyCPU | 4.5 | 12.0.0.0 | v12.0 |
| 2012 | Class Library | AnyCPU | 4.0 | 11.0.0.0 | v11.0 |
| 2010 | Class Library | AnyCPU | 4.0 | 10.0.0.0 | v10.0 |
| 2008 | Class Library | AnyCPU | 3.0 | 9.0.0.0 | v9.0 |
| 2005 | Class Library | AnyCPU | 2.0 | 8.0.0.0 | v8.0 |

Step two is to add the right references to it;

From the Visual Studio installation directory find:

  • Microsoft.TeamFoundation.VersionControl.Client.dll
  • Microsoft.TeamFoundation.Client.dll
  • Microsoft.TeamFoundation.dll

You can find these in: C:\Program Files (x86)\Microsoft Visual Studio {VisualStudioVersion}\Common7\IDE\PrivateAssemblies\.

Update: For Visual Studio 2015 and 2017, instead use the NuGet package.

Step 3, is to add a new class to it and have it inherit from PolicyBase.

Step 4, mark the class as [Serializable()].

If your code doesn't use any special features of the more recent versions of the Client Object Model, you can use "Add As Link" to add the same .cs to all the projects you've created in your solution.

Step 5 to each project add a compiler constant for the visual studio version you're targeting. This allows you to use #IF (VS2010) #ENDIF to add Visual Studio version specific code.

Now you're set to implement all the abstract methods of the PolicyBase class.

When you've implemented your policy you need to deploy it to all of your clients. This can either be done using a MSI, a VSIX, the Power Tools or manually. The key thing is to deploy the policy assemblies to the client and then adding a registry key to register your policy. Make sure you register for each version of Visual Studio by substituting the correct Visual Studio Version.

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\12.0\TeamFoundation\SourceControl\Checkin Policies]
"JesseHouwing.CheckinPolicies"="C:\Program Files(x86)\\MyCompany\\Checkin Policies\\v12.0\\JesseHouwing.CheckinPolicies.dll"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\TeamFoundation\SourceControl\Checkin Policies]
"JesseHouwing.CheckinPolicies"="C:\Program Files(x86)\\MyCompany\\Checkin Policies\\v12.0\\JesseHouwing.CheckinPolicies.dll"