<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sankofa &#187; TFS SDK</title>
	<atom:link href="http://blog.ianuy.com/tag/tfs-sdk/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ianuy.com</link>
	<description>From Script Kiddie to Professional Software Developer</description>
	<lastBuildDate>Tue, 18 May 2010 16:09:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Laziness, Impatience and Hubris or How to download Work Item attachments programatically using TFS SDK</title>
		<link>http://blog.ianuy.com/2010/01/24/laziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk/</link>
		<comments>http://blog.ianuy.com/2010/01/24/laziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 10:50:48 +0000</pubDate>
		<dc:creator>Ian Uy</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[TFS SDK]]></category>

		<guid isPermaLink="false">http://blog.ianuy.com/?p=562</guid>
		<description><![CDATA[Larry Wall, the creator of the infamous Perl programming language, has once said that the greatest virtues of a good programmer are Laziness, Impatience and Hubris. To not mislead the lazy &#8220;computer science&#8221; students, allow me to define each virtues:

Laziness &#8212; The quality that makes you go to great effort to reduce overall energy expenditure. [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_563" class="wp-caption aligncenter" style="width: 235px"><a href="http://blog.ianuy.com/wp-content/uploads/2010/01/larry_wall_haz_dem.JPG"><img class="size-medium wp-image-563" title="larry_wall_haz_dem" src="http://blog.ianuy.com/wp-content/uploads/2010/01/larry_wall_haz_dem-225x300.jpg" alt="Larry Wall haz dem" width="225" height="300" /></a><p class="wp-caption-text">Larry Wall haz dem</p></div>
<p><a title="Larry Wall" href="http://en.wikipedia.org/wiki/Larry_Wall" target="_blank">Larry Wall</a>, the creator of the infamous <a title="Perl" href="http://en.wikipedia.org/wiki/Perl" target="_blank">Perl programming language</a>, has once said that the greatest virtues of a good programmer are <a title="Don't you believe me?" href="http://en.wikipedia.org/wiki/Larry_Wall#Virtues_of_a_programmer" target="_blank">Laziness, Impatience and Hubris</a>. To not mislead the lazy &#8220;computer science&#8221; students, allow me to define each virtues:</p>
<ol>
<li><strong>Laziness</strong> &#8212; The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful, and document what you wrote so you don&#8217;t have to answer so many questions about it. Hence, the first great virtue of a programmer. See also impatience and hubris.</li>
<li><strong>Impatience </strong>&#8211; The anger you feel when the computer is being lazy. This makes you write  programs that don&#8217;t just react to your needs, but actually anticipate  them. Or at least pretend to. Hence, the second great virtue of a  programmer. See also laziness and hubris.</li>
<li><strong>Hubris </strong>&#8211; Excessive pride. Also the quality that makes you write (and maintain) programs that other  people won&#8217;t want to say bad things about. Hence, the third great  virtue of a programmer. See also laziness and impatience.</li>
</ol>
<p>A few days ago, a tester at our company filled a track that contained multiple attachments (Screenshots, Error Logs, etc) to assist the developers on their investigation. As we are using <a title="TFS?" href="http://en.wikipedia.org/wiki/Team_Foundation_Server" target="_blank">Microsoft&#8217;s Team Foundation System</a> for source control and bug tracking, the most obvious way to get these attachments is through TFS Web Access; Frankly speaking, this is the <strong>only</strong> &#8220;official&#8221; way to access the track (bug report) on our company.</p>
<div id="attachment_564" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.ianuy.com/wp-content/uploads/2010/01/TFSWA.png"><img class="size-medium wp-image-564" title="TFSWA" src="http://blog.ianuy.com/wp-content/uploads/2010/01/TFSWA-300x217.png" alt="The TFS Web Access homepage UI" width="300" height="217" /></a><p class="wp-caption-text">The TFS Web Access homepage UI</p></div>
<p>I don&#8217;t know if its a lack of feature or what, but there is no way in TFS Web Access to download multiple attachments at once. Additionally, when downloading attachments that contains a space on their filename, TFS Web Access will automatically concatenate the filename and that will remove the file&#8217;s extension (EG: <em>Screenshot of the bug.jpg</em> will be renamed to <em>Screenshot</em>)&#8230; You still need to manually rename the file with the proper extension to open it. And because I&#8217;m lazy, I don&#8217;t want <span style="text-decoration: underline;">to log-in to TFS Web Access, type in the track ID, click on the attachments tab, click on the file(s) I want to download, browse for the location where to save the file, create a new folder for the track, click save, minimize my browser, open the download location and (unzip the attachment, it its zipped, which normally is)</span> to just view a single screenshot.</p>
<p>Since I am a big believer of Wall&#8217;s three virtues, I created a tool that will automate those boring and repetitive tasks for me (and allow me to download *all* attachments from a work item + workaround the &#8220;spacing&#8221; bug). The tool is called <strong>WIF </strong>or Work Item Fetcher and it is currently in Closed-Limited Beta.</p>
<p>At first, I thought about parsing the web pages to download the attachments using HTML Sanitizers and Regular Expressions but then I remembered that only <a title="Parsing Html The Cthulhu Way" href="http://www.codinghorror.com/blog/archives/001311.html" target="_blank">Chuck Norris can parse HTML using regular expressions</a>! So I searched the web and found out about the <a title="TFS SDK" href="http://msdn.microsoft.com/en-us/library/bb130146%28VS.80%29.aspx" target="_blank">TFS SDK</a>! Go .NET! Go Laziness! Okay, enough chit-chat, the rest of the post will be dedicated to discussing how to use the TFS API to download attachments from TFS. <img src='http://blog.ianuy.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> </p>
<p><span id="more-562"></span></p>
<h1><span style="text-decoration: underline;">Step 1: Acquiring the needed libraries</span></h1>
<p>To be honest, I don&#8217;t really know where to download the DLLs. I&#8217;ve searched and found nothing. What I did was I referenced the DLLs located at <span style="text-decoration: underline;">C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies</span>\. The DLLs should be available after you download and install <a title="Get it here!" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=46473C2A-BB85-4461-BB27-4792A5DEF222&amp;displaylang=en" target="_blank">Team Explorer for Visual Studio 2005</a>. For our purposes, you should reference the following DLLs:</p>
<ul>
<li>Microsoft.TeamFoundation.DLL</li>
<li>Microsoft.TeamFoundation.Client.DLL</li>
<li>Microsoft.TeamFoundation.WorkItemTracking.Client.DLL</li>
</ul>
<p>You must then add the needed declarations like so:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.TeamFoundation</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.TeamFoundation.Client</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.TeamFoundation.WorkItemTracking.Client</span><span style="color: #008000;">;</span></pre></div></div>

<p>Compile your project to check. <img src='http://blog.ianuy.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Remember to always compile your project after each step.</p>
<h1><span style="text-decoration: underline;">Step 2: Connecting to your TFS server</span></h1>
<p>If you want to do <em>anything</em> with your TFS SDK, the first thing that you should do is to connect to your TFS server. Connecting is straight-forward, but a little tricky if you need to provide your network credentials. First, lets assume that the program will run on a machine that is connected to the domain with the proper credentials (AKA straight-forward way):</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">const</span> <span style="color: #FF0000;">string</span> TFSServer <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;http://mytfsserver:8090&quot;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>TeamFoundationServer tfsConn <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TeamFoundationServer<span style="color: #000000;">&#40;</span>TFSServer<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">try</span>
	<span style="color: #000000;">&#123;</span>
		tfsConn.<span style="color: #0000FF;">EnsureAuthenticated</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception ex<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		MessageBox.<span style="color: #0000FF;">Show</span><span style="color: #000000;">&#40;</span>ex.<span style="color: #0000FF;">Message</span>, <span style="color: #666666;">&quot;Cannot connect to TFS Server!&quot;</span>, MessageBoxButtons.<span style="color: #0000FF;">OK</span>, MessageBoxIcon.<span style="color: #0000FF;">Error</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>A call to <strong>EnsureAuthenticated();</strong> is needed to check if your connection is properly authenticated. If not, the method will throw an exception.</p>
<p>How about if you need to manually provide login credentials or your machine is not joined to a domain? Just use the NetCredential object from <strong>System.Net</strong> to pass your credentials:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">const</span> <span style="color: #FF0000;">string</span> TFSServer <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;http://mytfsserver:8090&quot;</span><span style="color: #008000;">;</span>
&nbsp;
NetworkCredential netCred <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> NetworkCredential<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Username&quot;</span>, <span style="color: #666666;">&quot;Password&quot;</span>, <span style="color: #666666;">&quot;Domain&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>TeamFoundationServer tfsConn <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TeamFoundationServer<span style="color: #000000;">&#40;</span>TFSServer, netCred<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">try</span>
	<span style="color: #000000;">&#123;</span>
		tfsConn.<span style="color: #0000FF;">EnsureAuthenticated</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception ex<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		MessageBox.<span style="color: #0000FF;">Show</span><span style="color: #000000;">&#40;</span>ex.<span style="color: #0000FF;">Message</span>, <span style="color: #666666;">&quot;Cannot connect to TFS Server!&quot;</span>, MessageBoxButtons.<span style="color: #0000FF;">OK</span>, MessageBoxIcon.<span style="color: #0000FF;">Error</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<h1><span style="text-decoration: underline;">Step 3: Acquire the Work Item</span></h1>
<p>Now that we&#8217;re good and connected to TFS, our next task is to acquire the Work Item from TFS. First, we&#8217;ll need to acquire the WorkItemStore service from TFS by calling the <strong>GetService</strong> method:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">WorkItemStore wis <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span>tfsServer.<span style="color: #0000FF;">GetService</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Then, we&#8217;ll get the Work Item by invoking the <strong>GetWorkItem </strong>method:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">WorkItem wi <span style="color: #008000;">=</span> wis.<span style="color: #0000FF;">GetWorkItem</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">1000</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Where 1000 is the Work Item ID</span></pre></div></div>

<p>Now, your code should look something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">const</span> <span style="color: #FF0000;">string</span> TFSServer <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;http://mytfsserver:8090&quot;</span><span style="color: #008000;">;</span>
&nbsp;
NetworkCredential netCred <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> NetworkCredential<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Username&quot;</span>, <span style="color: #666666;">&quot;Password&quot;</span>, <span style="color: #666666;">&quot;Domain&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>TeamFoundationServer tfsConn <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TeamFoundationServer<span style="color: #000000;">&#40;</span>TFSServer, netCred<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">try</span>
	<span style="color: #000000;">&#123;</span>
		tfsConn.<span style="color: #0000FF;">EnsureAuthenticated</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                WorkItemStore wis <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span>tfsServer.<span style="color: #0000FF;">GetService</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                WorkItem wi <span style="color: #008000;">=</span> wis.<span style="color: #0000FF;">GetWorkItem</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">1000</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Where 1000 is the Work Item ID</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception ex<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		MessageBox.<span style="color: #0000FF;">Show</span><span style="color: #000000;">&#40;</span>ex.<span style="color: #0000FF;">Message</span>, <span style="color: #666666;">&quot;Something has gone wrong!&quot;</span>, MessageBoxButtons.<span style="color: #0000FF;">OK</span>, MessageBoxIcon.<span style="color: #0000FF;">Error</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<h1><span style="text-decoration: underline;">Step 4: Get the attachments&#8217; URI</span></h1>
<p>After acquiring the Work Item, we can now directly iterate through the attachment collection to access its attachment&#8217;s URI:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">foreach</span><span style="color: #000000;">&#40;</span>Attachment attachment <span style="color: #0600FF;">in</span> wi.<span style="color: #0000FF;">Attachments</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #FF0000;">string</span> FileName <span style="color: #008000;">=</span> attachment.<span style="color: #0000FF;">Name</span><span style="color: #008000;">;</span>
	<span style="color: #FF0000;">string</span> attachmentURI <span style="color: #008000;">=</span> attachment.<span style="color: #0000FF;">Uri</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Cool huh? Just like that! Your entire code should look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">const</span> <span style="color: #FF0000;">string</span> TFSServer <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;http://mytfsserver:8090&quot;</span><span style="color: #008000;">;</span>
&nbsp;
NetworkCredential netCred <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> NetworkCredential<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Username&quot;</span>, <span style="color: #666666;">&quot;Password&quot;</span>, <span style="color: #666666;">&quot;Domain&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>TeamFoundationServer tfsConn <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TeamFoundationServer<span style="color: #000000;">&#40;</span>TFSServer, netCred<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">try</span>
	<span style="color: #000000;">&#123;</span>
		tfsConn.<span style="color: #0000FF;">EnsureAuthenticated</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                WorkItemStore wis <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span>tfsServer.<span style="color: #0000FF;">GetService</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                WorkItem wi <span style="color: #008000;">=</span> wis.<span style="color: #0000FF;">GetWorkItem</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">1000</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Where 1000 is the Work Item ID</span>
&nbsp;
		<span style="color: #0600FF;">foreach</span><span style="color: #000000;">&#40;</span>Attachment attachment <span style="color: #0600FF;">in</span> wi.<span style="color: #0000FF;">Attachments</span><span style="color: #000000;">&#41;</span>
		<span style="color: #000000;">&#123;</span>
			<span style="color: #FF0000;">string</span> FileName <span style="color: #008000;">=</span> attachment.<span style="color: #0000FF;">Name</span><span style="color: #008000;">;</span>
			<span style="color: #FF0000;">string</span> attachmentURI <span style="color: #008000;">=</span> attachment.<span style="color: #0000FF;">Uri</span><span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception ex<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		MessageBox.<span style="color: #0000FF;">Show</span><span style="color: #000000;">&#40;</span>ex.<span style="color: #0000FF;">Message</span>, <span style="color: #666666;">&quot;Something has gone wrong!&quot;</span>, MessageBoxButtons.<span style="color: #0000FF;">OK</span>, MessageBoxIcon.<span style="color: #0000FF;">Error</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<h1><span style="text-decoration: underline;">Step 5: Downloading the attachments</span></h1>
<p>And now that we have the attachment&#8217;s URI, all there is left to do is to download it. Thankfully, .NET provided us with the WebClient class that simplifies the downloading:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>WebClient wClient <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> WebClient<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	wClient.<span style="color: #0000FF;">Credentials</span> <span style="color: #008000;">=</span> netCred<span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Provide your network credentials.</span>
	wClient.<span style="color: #0000FF;">DownloadFile</span><span style="color: #000000;">&#40;</span>attachment.<span style="color: #0000FF;">Uri</span>, Path.<span style="color: #0000FF;">Combine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">@&quot;C:&quot;</span>, attachment.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>That&#8217;s it! You&#8217;re done. <img src='http://blog.ianuy.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  The completed code should look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>TeamFoundationServer tfsConn <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TeamFoundationServer<span style="color: #000000;">&#40;</span>TFSServer, netCred<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">try</span>
	<span style="color: #000000;">&#123;</span>
		tfsConn.<span style="color: #0000FF;">EnsureAuthenticated</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                WorkItemStore wis <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span>tfsServer.<span style="color: #0000FF;">GetService</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>WorkItemStore<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                WorkItem wi <span style="color: #008000;">=</span> wis.<span style="color: #0000FF;">GetWorkItem</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">1000</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Where 1000 is the Work Item ID</span>
&nbsp;
		<span style="color: #0600FF;">foreach</span><span style="color: #000000;">&#40;</span>Attachment attachment <span style="color: #0600FF;">in</span> wi.<span style="color: #0000FF;">Attachments</span><span style="color: #000000;">&#41;</span>
		<span style="color: #000000;">&#123;</span>
			<span style="color: #FF0000;">string</span> FileName <span style="color: #008000;">=</span> attachment.<span style="color: #0000FF;">Name</span><span style="color: #008000;">;</span>
			<span style="color: #FF0000;">string</span> attachmentURI <span style="color: #008000;">=</span> attachment.<span style="color: #0000FF;">Uri</span><span style="color: #008000;">;</span>
&nbsp;
			<span style="color: #0600FF;">using</span> <span style="color: #000000;">&#40;</span>WebClient wClient <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> WebClient<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
			<span style="color: #000000;">&#123;</span>
				wClient.<span style="color: #0000FF;">Credentials</span> <span style="color: #008000;">=</span> netCred<span style="color: #008000;">;</span>
				wClient.<span style="color: #0000FF;">DownloadFile</span><span style="color: #000000;">&#40;</span>attachmentURI, Path.<span style="color: #0000FF;">Combine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">@&quot;C:&quot;</span>, FileName<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
		<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception ex<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		MessageBox.<span style="color: #0000FF;">Show</span><span style="color: #000000;">&#40;</span>ex.<span style="color: #0000FF;">Message</span>, <span style="color: #666666;">&quot;Something has gone wrong!&quot;</span>, MessageBoxButtons.<span style="color: #0000FF;">OK</span>, MessageBoxIcon.<span style="color: #0000FF;">Error</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<h1><span style="text-decoration: underline;">Step 6: Optional Improvements</span></h1>
<p>The code above is the minimum required to have a fully functional attachment downloader for TFS. There are a couple of things that you can do to improve your program:</p>
<ul>
<li>Automatically create a directory for each Work Item. This way, you will have an organized local storage of the attachments.</li>
<li>Instead of using the DownloadFile method to download your file, you can use the <a title="MSDN" href="http://msdn.microsoft.com/en-us/library/system.net.webclient.downloadfileasync.aspx" target="_blank">DownloadFileAsync </a>method to download the file asynchronously. DownloadFileAsync is non-thread blocking. This call will also allow you to listen to EventHandlers for the download progress.</li>
<li>After the download, you can check if the file is a zip file (by using <a title="MSDN" href="http://msdn.microsoft.com/en-us/library/system.io.path.getextension.aspx" target="_blank">Path.GetExtension</a>), and if it is, you can use <a title="SharpZipLib" href="http://www.icsharpcode.net/OpenSource/SharpZipLib/" target="_blank">SharpZipLib</a> to automatically unzip the package.</li>
<li>Sometimes, instead of providing the Incident number, your users will provide the Incident Fix number. Its good to anticipate that and provide a way to resolve the Incident Number from the Incident Fix. To do that, first check if your user provided an Incident Fix by calling <strong>wi.Fields.GetById(25).Value.ToString() == &#8220;Incident Fix&#8221;</strong> then if yes, you can get the Incident Number by calling <strong>int ParentID = (int)wi.Fields.GetById(10120).Value</strong>. <em>Thank you Impatience!</em></li>
</ul>
<p>I can&#8217;t really share my program with you guys (you know all of that &#8220;corporate&#8221; legal mumbo-jumbo). But here&#8217;s the screenshot:</p>
<div id="attachment_594" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.ianuy.com/wp-content/uploads/2010/01/WIF.png"><img class="size-medium wp-image-594" title="WIF" src="http://blog.ianuy.com/wp-content/uploads/2010/01/WIF-300x247.png" alt="Work Item Fetcher @ TFS" width="300" height="247" /></a><p class="wp-caption-text">Work Item Fetcher @ TFS</p></div>
<p>Thank you Laziness for making me go to great effort to reduce the total effort and time needed to download attachments from TFS. Thank you for making me write labor-saving programs that other people will hopefully find useful.</p>
<p>Thank you Impatience for pissing me off when I am manually downloading and renaming attachments one by one. Thank you too for making me angry when my initial prototype failed when I gave it an Incident Fix number rather than an Incident number.</p>
<p>And, as always, thank you Hubris! <img src='http://blog.ianuy.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  (People around me knows exactly why!)</p>



Share and Enjoy:


	<a rel="nofollow" href="mailto:?subject=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK&amp;body=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F" title="E-mail this story to a friend!"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/email_link.png" title="E-mail this story to a friend!" alt="E-mail this story to a friend!" class="sociable-hovers" /></a>
	<a rel="nofollow" target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;title=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK&amp;bodytext=%0A%0D%0ALarry%20Wall%2C%20the%20creator%20of%20the%20infamous%20Perl%20programming%20language%2C%20has%20once%20said%20that%20the%20greatest%20virtues%20of%20a%20good%20programmer%20are%20Laziness%2C%20Impatience%20and%20Hubris.%20To%20not%20mislead%20the%20lazy%20%22computer%20science%22%20students%2C%20allow%20me%20to%20define%20each%20virtu" title="Digg"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow" target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;title=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK" title="Reddit"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow" target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;title=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK&amp;notes=%0A%0D%0ALarry%20Wall%2C%20the%20creator%20of%20the%20infamous%20Perl%20programming%20language%2C%20has%20once%20said%20that%20the%20greatest%20virtues%20of%20a%20good%20programmer%20are%20Laziness%2C%20Impatience%20and%20Hubris.%20To%20not%20mislead%20the%20lazy%20%22computer%20science%22%20students%2C%20allow%20me%20to%20define%20each%20virtu" title="del.icio.us"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow" href="http://twitter.com/home?status=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK%20-%20http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F" title="Twitter"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>
	<a rel="nofollow" target="_blank" href="http://slashdot.org/bookmark.pl?title=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK&amp;url=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F" title="Slashdot"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/slashdot.png" title="Slashdot" alt="Slashdot" class="sociable-hovers" /></a>
	<a rel="nofollow" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;t=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK" title="Facebook"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow" href="http://www.myspace.com/Modules/PostTo/Pages/?u=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;t=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK" title="MySpace"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/myspace.png" title="MySpace" alt="MySpace" class="sociable-hovers" /></a>
	<a rel="nofollow" target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;title=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK&amp;annotation=%0A%0D%0ALarry%20Wall%2C%20the%20creator%20of%20the%20infamous%20Perl%20programming%20language%2C%20has%20once%20said%20that%20the%20greatest%20virtues%20of%20a%20good%20programmer%20are%20Laziness%2C%20Impatience%20and%20Hubris.%20To%20not%20mislead%20the%20lazy%20%22computer%20science%22%20students%2C%20allow%20me%20to%20define%20each%20virtu" title="Google Bookmarks"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow" target="_blank" href="http://www.dotnetkicks.com/kick/?url=http%3A%2F%2Fblog.ianuy.com%2F2010%2F01%2F24%2Flaziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk%2F&amp;title=Laziness%2C%20Impatience%20and%20Hubris%20or%20How%20to%20download%20Work%20Item%20attachments%20programatically%20using%20TFS%20SDK" title="DotNetKicks"><img src="http://blog.ianuy.com/wp-content/plugins/sociable/images/dotnetkicks.png" title="DotNetKicks" alt="DotNetKicks" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://blog.ianuy.com/2010/01/24/laziness-impatience-and-hubris-or-how-to-download-work-item-attachments-programatically-using-tfs-sdk/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
