Copying TFS Work Items

So you want to copy a work item (WI)? Well TFS does indeed have a copy command via the UI which will create a new work item based upon a certain type.

The issue here is that this could be a timely process based upon the number of copies that need to be made. Not to mention the fact that this is a one off process so bulk copying, say 200 WI's (i.e. User Stories) is just not possible.

That said, with a little bit of code and using the Visual Studio Team Foundation Server SDK, it’s possible to harness this functionality to copy a WI as opposed to using the UI. While this code only converts one WI (i.e. User Story -> Task), it’s not a stretch to customize it to iterate through a list of WI’s. As always, a word of caution - use this code at your own risk as using the TFS namespaces directly could severely damage your backlog.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System.Net;

namespace workItemConvert

{

    class ConvertWI

    {

        static int Main(string[] args)

        {

            //Show syntax if no arguments are passed in or user asks for help

            if (args.Length < 3 ||

                args[0].ToLower() == "/h" ||

                args[0].ToLower() == "-h"

              )

            {

                showSyntax();

                return 1;

            }

            string tfsCollectionURI = args[0];

            string sourceWorkItemID = args[1];

            string targetWorkItemType = args[2];

            ICredentialsProvider provider = new UICredentialsProvider();

            TfsTeamProjectCollection targettfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsCollectionURI), provider);

            try

            {

                targettfs.Authenticate();

            }

            catch (Exception e)

            {

                Console.WriteLine(e.InnerException);

            }

            WorkItemStore wis = targettfs.GetService<WorkItemStore>();

            WorkItemCollection wic = wis.Query("SELECT [System.Id] FROM WorkItems WHERE [System.Id] = " + sourceWorkItemID);

            //Detect task work item type

            WorkItemType wiTypeTask = null;

            foreach (WorkItemType wiTypeTemp in wis.Projects[0].WorkItemTypes)

            {

        if (wiTypeTemp.Name.ToLower().Equals(targetWorkItemType))

                {

                    wiTypeTask = wiTypeTemp;

                }

            }

            foreach (WorkItem wi in wic)

            {

                WorkItem copy = wi.Copy(wiTypeTask, WorkItemCopyFlags.CopyFiles | WorkItemCopyFlags.CopyLinks);

                copy.Save();

                Console.WriteLine("Source ID: {0} Target ID: {1}", wi.Id, copy.Id);

            }

            return 0;

        }

        private static void showSyntax()

        {

            string thisFileName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

            Console.WriteLine("Copies work item to another work item type.");

            Console.WriteLine();

          Console.WriteLine("Usage: " + thisFileName + " [TFS Collection URL] [Source Work Item ID] [Target Work Item Type]");

            Console.WriteLine();

            Console.WriteLine("Example: " + thisFileName + " https://MYTFS:8080/tfs/MyProjects 257 Task");

            Console.WriteLine();

            Console.WriteLine("This example would copy work item ID 257 to a task work item.");

        }

    }

}