Automation to relate TFS work items

If you are using TFS 2008 for work item tracking be sure to get most out of the tool by relating work items.  Depending on the process template you are using the work item types may be different.  In general terms consider linking your requirement/scenario/use cases with tasks.

If you are using the MSF for Agile template this would translate to linking scenario work item with one or more tasks required to implement than scenario.

While there is no actual work item parent/child relationship in TFS 2008 you can still construct meaningful work progress reports from a peer scenario and task work item relationship.   I’ll go into more detail on how to get this project status info in a later post.

Here I want to focus on how to link work items in bulk.  TFS 2008 does not have a way to bulk link work items; not through Team Explorer, not through Excel and not through Project.  Darn, darn, darn.

This means if you have imported scores of work items, say via Excel, you would have to open each scenario work item in Team Explorer and manually link the associated tasks with that scenario (instructions to do this manually are here).

For most folks all this manual work would be a reasonable barrier to entry and they would just abandon linking work items and the associated project reporting benefits.

Bulk linking of work items may be better in TFS 2010.  Until then I offer you the code below for a command line utility that will link a work item with one or more other work items. 

Example syntax looks like this:

linkWorkItems.exe https://tfsrtm08:8080 sandbox 659 "660,661,662,663”

This would link work item 659 to work items 660, 661, 662 and 663.

One great reference I used was this link below to Shai Raiten’s blog. 

Reference Link

https://blogs.microsoft.co.il/blogs/shair/archive/2008/10/06/more-about-creating-work-item-using-tfs-api.aspx

Code

 using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace linkWorkItems
{
    class Program
    {
        static int Main(string[] args)
        {
            //show syntax if no arguments are passed in or user asks for help
            if (args.Length < 4 ||
                args[0].ToLower() == "/h" ||
                args[0].ToLower() == "-h" ||
                args[0].ToLower() == "/?" ||
                args[0].ToLower() == "-?"
                )
            {
                showSyntax();
                return 1;
            }
            string serverName = args[0].ToString();
            string projectName = args[1].ToString();
            string parentWorkItemID = args[2].ToString();
            string [] childWorkItemIDs = args[3].Split(',');

            //connect to TFS
            TeamFoundationServer tfs = null;
            WorkItemStore store = null ;
            Project project = null ;
            try
            {
                tfs = new TeamFoundationServer(serverName);
                store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
                project = store.Projects[projectName];
            }
            catch (Exception e)
            {
                Console.WriteLine("Error:" + e.Message);
                return 2;
            }

            //get parent work item
            WorkItem parentWorkItem = null;
            try
            {
                parentWorkItem = project.Store.GetWorkItem(int.Parse(parentWorkItemID));
            }
            catch (Exception e) 
            {
                Console.WriteLine("Error:" + e.Message );
                return 3;
            }

            //iterate through child work items that we want to link to parent work item
            foreach (string childWorkItemID in childWorkItemIDs)
            {
                //create related work item link
                RelatedLink rl = new RelatedLink(int.Parse(childWorkItemID));
                Console.WriteLine("Linking work item ID " + childWorkItemID + " to " + parentWorkItemID) ; 
                try
                {
                    parentWorkItem.Links.Add(rl);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Warning:" + e.Message);
                }

            }
            //save new links to parent work item
            try
            {
                parentWorkItem.Save();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error:" + e.Message) ;
                return 4;
            }
            //complete
            return 0;
        }
        private static void showSyntax()
        {
            string thisFileName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
            Console.WriteLine("Utility to link one or more work items to another work item.");
            Console.WriteLine();
            Console.WriteLine("Usage: " + thisFileName + " [Team Server] [Project] [parent work item ID] [\"child ID1,ID2,ID3\"]");
            Console.WriteLine();
            Console.WriteLine("Example: " + thisFileName + " https://MYTFS:8080 sandbox 559 \"560,561,562\" ");

        }
        
    }
}

If you have other ways bulk link work items let me know in the comments.  Be sure to leave a comment and link to other tools that solve this same problem too.