The company I work for (Delta-N), is a service company. We built software for various customers and we do so by means of projects. It should not surprise you that we maintain all our development projects in Team Foundation Server and, since we use TFS since the first version (TFS 2005), we do have a lot of them.
Since 2 years we use the Microsoft Scrum template for our projects and we customized it quite a bit. Even today, we regularly think of new reports, extra fields etc. that helps us to do our job better.
The whole idea of Process Templates in Team Foundation Server is based on the fact that you create a baseline for your new projects so that you can continuously improve. And that is what we do. We modify the current Team Project with our change and, if it is ok, we put the change in a new version of our Process Template. Then we roll out the changes to other Team Projects that are still active so they can also make use of the improvements.
We found that it was very hard to see on which version of a Process Template a Team Project was based on. Especially when the changes are small, it would be great to be able to see the Process Template version and then decide to either roll out the change or not.
In Team Foundation Server there is nothing on screen that you can check to obtain the version so I checked the API. Tarun wrote a post about getting the Process Template with the TFS API, but that was not enough for me. I want to keep track of the Process Template Version with which the project was created, but also which version the Team Project currently uses, so I can make decisions based on this fact.
After some contact with the Product Team, Ewald Hofman gave me the solution. Extra properties can be added to the Classification.xml file in which you can keep track of all kinds of data.
The solution
With this information in mind, I wrote a small utility that allows you to list process template, created version and current version of a Team Project. The created and current version are custom properties.
Let me walk you through my solution.
The program lets you connect to a Team Project Collection and select the Team Projects you would like to work on. Once you select the projects, the list fills up with Team Projects, the Created Version Custom Property, The Current Version Custom Property and the Process Template property which is default in all Process Templates of TFS 2012.
Once you select a project, the textboxes fill up. When the properties do not exist, “Not Set” will be shown. By clicking update you can change (or add if it does not exist yet) the properties.
Inner workings
Let’s start with the beginning. When you download the Process Template from the Process template manager (click here to see how) you get a bunch of files and directories. When you navigate to the [Classification] folder and open the [Classification.xml], you’ll notice the following code.
<properties> <property name="MSPROJ" value="Classification\FieldMapping.xml" isFile="true" /> <property name="Process Template" value="Microsoft Visual Studio Scrum 2.2" /> </properties>
Add property lines for your own properties in this file.
<properties> <property name="MSPROJ" value="Classification\FieldMapping.xml" isFile="true" /> <property name="Process Template" value="Microsoft Visual Studio Scrum 2.2" /> <property name="Create Version" value="Custom Text is allowed here" /> <property name="Current Version" value="Custom Text is allowed here" /> </properties>
Now upload you Process Template and create a new Team Project.
Once the Team Project is created, you can read the properties by using this code.
string uri = @"http://myServer:8080/tfs/defaultcollection"; string teamProjectName = "myTeamProject"; // Get the team project var tpc = new TfsTeamProjectCollection(new Uri(uri)); tpc.Authenticate(); var ics = tpc.GetService<ICommonStructureService>(); var teamProject = ics.GetProjectFromName(teamProjectName); // Read the properties string projectName = string.Empty; string projectState = string.Empty; int templateId = 0; ProjectProperty[] projectProperties = null; ics.GetProjectProperties(teamProject.Uri, out projectName, out projectState,
out templateId, out projectProperties); // Return the properties string processtemplate = projectProperties.Where(p =>
(p.Name == "Process Template")).Select(p => p.Value).FirstOrDefault(); string currentVersion = projectProperties.Where(p =>
(p.Name == "Current version")).Select(p => p.Value).FirstOrDefault(); string createVersion = projectProperties.Where(p =>
(p.Name == "Create version")).Select(p => p.Value).FirstOrDefault(); //Update the properties projectProperties.Where(p => (p.Name == "Current version")).First().Value =
"MS Scrum 2.2 - Custom 2.3"; ics.UpdateProjectProperties(teamProject.Uri, projectState,
projectProperties);
In the tool I created there are some extra pieces of code, that allow you to add properties and some extra checks whether things exist.
By using this construction, you can now be sure of the version your Team Project is using
Hope this helps !
Download the tool (PTVersionCheck.zip) + sources here.
Update 19-02-2015:
For the people who want to use the source and/or contribute I created a Git Repo here:
https://github.com/renevanosnabrugge/TFS-ProcessTemplateVersionCheck
Is there anyway to update an already existing project and add these new properties?
Yes! The tool is capable of doing Just that ! If the properties do not exist it adds them !
Thanks a brilliant tool, it definitely helped solving a few questions here!
Just a note when running the code :
I ran the code in VS2013 with reference to Microsoft.TeamFoundation.Client [v4.0.30319] targeting TFS 2013 Update 4.
The retrieval of the “Current version” and “Create version” from the ProjectProperty[] then returned null.
When I inspected the returned ProjectProperty[] collection, I found the only difference being the capital “V” in the text “Version”.
Maybe it is something specific to my setup / template?
I just changed the casing in 2 places in the code to an uppercase “V”
p.Name == “Current version” -> p.Name == “Current Version”
p.Name == “Create version” -> p.Name == “Create Version”
It then worked perfect :- )
Thanks !