{"id":523,"date":"2012-02-01T06:31:00","date_gmt":"2012-02-01T06:31:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/buckh\/2012\/02\/01\/listing-the-work-items-associated-with-changesets-for-a-path\/"},"modified":"2012-02-01T06:31:00","modified_gmt":"2012-02-01T06:31:00","slug":"listing-the-work-items-associated-with-changesets-for-a-path","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/buckh\/listing-the-work-items-associated-with-changesets-for-a-path\/","title":{"rendered":"Listing the work items associated with changesets for a path"},"content":{"rendered":"<p>Philip wrote a simple app to list the work items associated with the changesets for a given path, and it&rsquo;s in some ways an enhanced update of <a href=\"http:\/\/blogs.msdn.com\/b\/narend\/archive\/2006\/08\/08\/691625.aspx\">Naren&rsquo;s post<\/a>.<\/p>\n<p>Given an URL to a collection and a server path (e.g., $\/myproject\/coolthing), it will list the work items that are associated with the most recent 25 checkins.&nbsp; This sample shows how to use the linking service to convert the work item artifact URIs that are stored with the changesets to get the core work item fields (ID, assigned to, state, type, and title).<\/p>\n<p>It will produce output like the following.<\/p>\n<blockquote>\n<p>Id: 352694 Title: Improve performance of queuing servicing jobs on Azure.<\/p>\n<\/blockquote>\n<p>You will need to reference the following DLLs to build this, all of which are found on the .NET tab of the Add Reference dialog in Visual Studio 2010.<\/p>\n<ul>\n<li>Microsoft.TeamFoundation.Client.dll<\/li>\n<li>Microsoft.TeamFoundation.Common.dll<\/li>\n<li>Microsoft.TeamFoundation.VersionControl.Client.dll<\/li>\n<\/ul>\n<pre><span style=\"color: blue\">using<\/span> System; \n<span style=\"color: blue\">using<\/span> System.Collections.Generic; \n<span style=\"color: blue\">using<\/span> System.Diagnostics; \n<span style=\"color: blue\">using<\/span> Microsoft.TeamFoundation; \n<span style=\"color: blue\">using<\/span> Microsoft.TeamFoundation.Client; \n<span style=\"color: blue\">using<\/span> Microsoft.TeamFoundation.VersionControl.Client; \n\n<span style=\"color: blue\">namespace<\/span> ListWorkItems \n{ \n    <span style=\"color: blue\">class<\/span> Program \n    { \n        <span style=\"color: blue\">static<\/span> <span style=\"color: blue\">void<\/span> Main(<span style=\"color: blue\">string<\/span>[] args) \n        { \n            <span style=\"color: blue\">if<\/span> (args.Length &lt; <span style=\"color: maroon\">2<\/span>)\n            { \n                Console.WriteLine(<span style=\"color: maroon\">\"Usage: listworkitems &lt;URL for TFS&gt; &lt;server path&gt;\"<\/span>); \n                Environment.Exit(<span style=\"color: maroon\">1<\/span>); \n            } \n\n            TfsTeamProjectCollection tpc = <span style=\"color: blue\">new<\/span> TfsTeamProjectCollection(<span style=\"color: blue\">new<\/span> Uri(args[<span style=\"color: maroon\">0<\/span>]));\n            VersionControlServer vcs = tpc.GetService&lt;VersionControlServer&gt;(); \n\n            <span style=\"color: green\">\/\/ Get the changeset artifact URIs for each changeset in the history query<\/span>\n            List&lt;String&gt; changesetArtifactUris = <span style=\"color: blue\">new<\/span> List&lt;String&gt;(); \n\n            <span style=\"color: blue\">foreach<\/span> (Object obj <span style=\"color: blue\">in<\/span> vcs.QueryHistory(args[<span style=\"color: maroon\">1<\/span>],                       <span style=\"color: green\">\/\/ path we care about ($\/project\/whatever)<\/span> \n                                                    VersionSpec.Latest,            <span style=\"color: green\">\/\/ version of that path<\/span>\n                                                    <span style=\"color: maroon\">0<\/span>,                             <span style=\"color: green\">\/\/ deletion ID (0 = not deleted)<\/span> \n                                                    RecursionType.Full,            <span style=\"color: green\">\/\/ entire tree - full recursion<\/span>\n                                                    <span style=\"color: blue\">null<\/span>,                          <span style=\"color: green\">\/\/ include changesets from all users<\/span>\n                                                    <span style=\"color: blue\">new<\/span> ChangesetVersionSpec(<span style=\"color: maroon\">1<\/span>),   <span style=\"color: green\">\/\/ start at the beginning of time<\/span>\n                                                    VersionSpec.Latest,            <span style=\"color: green\">\/\/ end at latest<\/span>\n                                                    <span style=\"color: maroon\">25<\/span>,                            <span style=\"color: green\">\/\/ only return this many<\/span>\n                                                    <span style=\"color: maroon\">false<\/span>,                         <span style=\"color: green\">\/\/ we don't want the files changed<\/span>\n                                                    <span style=\"color: maroon\">true<\/span>))                         <span style=\"color: green\">\/\/ do history on the path<\/span>\n            { \n                Changeset c = obj <span style=\"color: blue\">as<\/span> Changeset; \n                changesetArtifactUris.Add(c.ArtifactUri.AbsoluteUri); \n            } \n\n            <span style=\"color: green\">\/\/ We'll use the linking service to get information about the associated work items<\/span>\n            ILinking linkingService = tpc.GetService&lt;ILinking&gt;(); \n            LinkFilter linkFilter = <span style=\"color: blue\">new<\/span> LinkFilter(); \n            linkFilter.FilterType = FilterType.ToolType; \n            linkFilter.FilterValues = <span style=\"color: blue\">new<\/span> String[<span style=\"color: maroon\">1<\/span>] { ToolNames.WorkItemTracking };  <span style=\"color: green\">\/\/ we only want work itms<\/span>\n\n            <span style=\"color: green\">\/\/ Convert the artifact URIs for the work items into strongly-typed objects holding the properties rather than name\/value pairs<\/span> \n            Artifact[] artifacts = linkingService.GetReferencingArtifacts(changesetArtifactUris.ToArray(), <span style=\"color: blue\">new<\/span> LinkFilter[<span style=\"color: maroon\">1<\/span>] { linkFilter });\n            AssociatedWorkItemInfo[] workItemInfos = AssociatedWorkItemInfo.FromArtifacts(artifacts);\n\n            <span style=\"color: green\">\/\/ Here we'll just print the IDs and titles of the work items<\/span>\n            <span style=\"color: blue\">foreach<\/span> (AssociatedWorkItemInfo workItemInfo <span style=\"color: blue\">in<\/span> workItemInfos)\n            { \n                Console.WriteLine(<span style=\"color: maroon\">\"Id: \"<\/span> + workItemInfo.Id + <span style=\"color: maroon\">\" Title: \"<\/span> + workItemInfo.Title); \n            } \n        } \n    } \n\n    <span style=\"color: blue\">internal<\/span> <span style=\"color: blue\">class<\/span> AssociatedWorkItemInfo\n    { \n        <span style=\"color: blue\">private<\/span> AssociatedWorkItemInfo() \n        { \n        } \n\n        <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">int<\/span> Id \n        { \n            <span style=\"color: blue\">get<\/span> \n            { \n                <span style=\"color: blue\">return<\/span> m_id; \n            } \n        } \n\n        <span style=\"color: blue\">public<\/span> String Title \n        { \n            <span style=\"color: blue\">get<\/span> \n            { \n                <span style=\"color: blue\">return<\/span> m_title; \n            } \n        } \n\n        <span style=\"color: blue\">public<\/span> String AssignedTo \n        { \n            <span style=\"color: blue\">get<\/span> \n            { \n                <span style=\"color: blue\">return<\/span> m_assignedTo; \n            } \n        } \n\n        <span style=\"color: blue\">public<\/span> String WorkItemType \n        { \n            <span style=\"color: blue\">get<\/span> \n            { \n                <span style=\"color: blue\">return<\/span> m_type; \n            } \n        } \n\n        <span style=\"color: blue\">public<\/span> String State \n        { \n            <span style=\"color: blue\">get<\/span> \n            { \n                <span style=\"color: blue\">return<\/span> m_state; \n            } \n        } \n\n        <span style=\"color: blue\">internal<\/span> <span style=\"color: blue\">static<\/span> AssociatedWorkItemInfo[] FromArtifacts(IEnumerable&lt;Artifact&gt; artifacts)\n        { \n            <span style=\"color: blue\">if<\/span> (<span style=\"color: blue\">null<\/span> == artifacts)\n            { \n                <span style=\"color: blue\">return<\/span> <span style=\"color: blue\">new<\/span> AssociatedWorkItemInfo[<span style=\"color: maroon\">0<\/span>];\n            } \n\n            List&lt;AssociatedWorkItemInfo&gt; toReturn = <span style=\"color: blue\">new<\/span> List&lt;AssociatedWorkItemInfo&gt;(); \n\n            <span style=\"color: blue\">foreach<\/span> (Artifact artifact <span style=\"color: blue\">in<\/span> artifacts)\n            { \n                <span style=\"color: blue\">if<\/span> (artifact == <span style=\"color: blue\">null<\/span>)\n                { \n                    <span style=\"color: blue\">continue<\/span>; \n                } \n\n                AssociatedWorkItemInfo awii = <span style=\"color: blue\">new<\/span> AssociatedWorkItemInfo();\n\n                <span style=\"color: green\">\/\/ Convert the name\/value pairs into strongly-typed objects containing the work item info<\/span> \n                <span style=\"color: blue\">foreach<\/span> (ExtendedAttribute ea <span style=\"color: blue\">in<\/span> artifact.ExtendedAttributes)\n                { \n                    <span style=\"color: blue\">if<\/span> (String.Equals(ea.Name, <span style=\"color: maroon\">\"System.Id\"<\/span>, StringComparison.OrdinalIgnoreCase)) \n                    { \n                        <span style=\"color: blue\">int<\/span> workItemId; \n\n                        <span style=\"color: blue\">if<\/span> (Int32.TryParse(ea.Value, <span style=\"color: blue\">out<\/span> workItemId))\n                        { \n                            awii.m_id = workItemId; \n                        } \n                    } \n                    <span style=\"color: blue\">else<\/span> <span style=\"color: blue\">if<\/span> (String.Equals(ea.Name, <span style=\"color: maroon\">\"System.Title\"<\/span>, StringComparison.OrdinalIgnoreCase)) \n                    { \n                        awii.m_title = ea.Value; \n                    } \n                    <span style=\"color: blue\">else<\/span> <span style=\"color: blue\">if<\/span> (String.Equals(ea.Name, <span style=\"color: maroon\">\"System.AssignedTo\"<\/span>, StringComparison.OrdinalIgnoreCase)) \n                    { \n                        awii.m_assignedTo = ea.Value; \n                    } \n                    <span style=\"color: blue\">else<\/span> <span style=\"color: blue\">if<\/span> (String.Equals(ea.Name, <span style=\"color: maroon\">\"System.State\"<\/span>, StringComparison.OrdinalIgnoreCase)) \n                    { \n                        awii.m_state = ea.Value; \n                    } \n                    <span style=\"color: blue\">else<\/span> <span style=\"color: blue\">if<\/span> (String.Equals(ea.Name, <span style=\"color: maroon\">\"System.WorkItemType\"<\/span>, StringComparison.OrdinalIgnoreCase)) \n                    { \n                        awii.m_type = ea.Value; \n                    } \n                } \n\n                Debug.Assert(<span style=\"color: maroon\">0<\/span> != awii.m_id, <span style=\"color: maroon\">\"Unable to decode artifact into AssociatedWorkItemInfo object.\"<\/span>); \n\n                <span style=\"color: blue\">if<\/span> (<span style=\"color: maroon\">0<\/span> != awii.m_id)\n                { \n                    toReturn.Add(awii); \n                } \n            } \n\n            <span style=\"color: blue\">return<\/span> toReturn.ToArray(); \n        } \n\n        <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">int<\/span> m_id; \n        <span style=\"color: blue\">private<\/span> String m_title; \n        <span style=\"color: blue\">private<\/span> String m_assignedTo; \n        <span style=\"color: blue\">private<\/span> String m_type; \n        <span style=\"color: blue\">private<\/span> String m_state; \n    } \n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Philip wrote a simple app to list the work items associated with the changesets for a given path, and it&rsquo;s in some ways an enhanced update of Naren&rsquo;s post. Given an URL to a collection and a server path (e.g., $\/myproject\/coolthing), it will list the work items that are associated with the most recent 25 [&hellip;]<\/p>\n","protected":false},"author":94,"featured_media":10268,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[8,11,15],"class_list":["post-523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-team-foundation","tag-tfs-2010","tag-tfs-api"],"acf":[],"blog_post_summary":"<p>Philip wrote a simple app to list the work items associated with the changesets for a given path, and it&rsquo;s in some ways an enhanced update of Naren&rsquo;s post. Given an URL to a collection and a server path (e.g., $\/myproject\/coolthing), it will list the work items that are associated with the most recent 25 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/posts\/523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/users\/94"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/comments?post=523"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/posts\/523\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/media\/10268"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/media?parent=523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/categories?post=523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/buckh\/wp-json\/wp\/v2\/tags?post=523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}