January 2008 Archives

One of the most frequent questions I get when talking to people about TFS if how to upgrade from the freely downloadable 90-day TFS 2008 trial to a full version of TFS.  Our TFS 2008 license key arrived at the weekend, so I thought I would take the opportunity to record the process.  The first two steps have nothing to do with installing your license key, just purchasing it - but sadly are often the most complicated.  Installing the actual key once received, is pretty trivial as I hope you will see.

Step 1:  Purchase a TFS License Key.

This step is frequently mis-understood.  You have to pay for the full version of TFS.  Just because you are a partner of an MSDN subscriber, doesn't mean that you get TFS included.  As an MSDN Subscriber, depending on your subscription type you do get access to a 5-user limited version of TFS called "Team Foundation Server Workrgoup Edition".  However only Gold Partners or Partners with an ISV Competency get TFS included in their partner fees - everyone else has to purchase it.  When connecting to TFS, you also need to make sure you have enough Team Foundation Server Client Access Licenses (CAL's) to cover your use - if you have a Team Suite flavor of MSDN then that gives you one CAL.

Step 2: Obtain TFS License Key.

The license key for TFS will be printed on a little sticker on the back of the media that it arrives on.  If it didn't (perhaps because you purchased TFS via a volume licensing agreement) then there are ways around this to get the license key out of the media (look for a file called setup.sdb and open it in Notepad, look for [Product Key], usually at the bottom of the file, and you will find it there).

Because getting a TFS License Key usually involves the physical delivery of the media, you should make sure that you factor this time into your purchasing decision.  If (like most people) your purchasing process takes longer than you budgeted for - then you do have the ability to extend your TFS Trial by an additional 30-days.

Step 3: Enter TFS Maintanence Mode

Go to, Control Panel, Add Remove Programs.

 Add / Remove Programs

Then find Microsoft Visual Studio 2008 Team Foundation Server in the list and press Change/Remove

Team Foundation Server Maintanence Mode

Step 4: Enter the Full Key for TFS

At the bottom of the maintenance dialog, you have the option to enter your full license key. 

TFS2008 Maintence Dialog

Note that there was a bug in the RTM version of TFS 2008 that means that workgroup edition doesn't have the ability - see this post for details.  This is TFS 2008 90-day trial, so it works just fine for us.

Enter your license key and press Next.  Note that this will install the license key and fire up a command window for a few seconds while it restarts IIS for the TFS server.  Once you are finished, you will get the following dialog.

License upgrade complete

And you are complete.  If you really want to check that the new license key has taken hold, then you can fire up a copy of Brian Harry's VersionDetection tool to set your mind at rest.

Version Detection tool showing that my TFS has a proper license key installed.

And there you go - running the final release (9.0.21022.8) with no expiry date :-)

In a previous post, I talked about how Windows file sharing sucks over the WAN. This is particularly annoying for me when trying to view the log of a TFS Build - especially if that build has failed and I want to know why in a hurry. On my computer (sitting on the end of a VPN nearly 4000 miles from my TFS instance), there is a delay of about 50-70 seconds to view the log file depending on the size and the speed of the link at that moment in time.  During that time, Visual Studio is hanging waiting for the file to open.  The issue is compounded by the fact that the rest of the Team Build UI - and in fact the whole of TFS access in general - is so speedy over the same VPN link, that I really notice the time delay accessing build logs.

Therefore - it didn't take too many 70-seconds delays for me to fire up a second instance of Visual Studio to create a work-around.  In Visual Studio 2008 (and in the upcoming Teamprise 3.0 Team Build integration), if the log location provided is not a UNC style path (i.e. \\server\drop\build\BuildLog.txt) but a http:// address, then it will open the file in a browser instead.  Accessing the build log over http helps in two important ways.

  1. HTTP is much less latency sensitive than accessing a file from a Windows share
  2. A browser will display the contents of the file before it has finished loading.  When accessing the build log directly from a file share, the application (i.e. Notepad) will have to wait until it has recieved the whole file before displaying any of it to you.  These log files can get large - so the improvement in perceived speed is significant. (http:// urls are a lot more cross-platform friendly than UNC paths as well, which is nice for us Teamprise folks).

Therefore, I created  a quick and dirty ASP.NET page that accessing the build log for a particular build over the network and streams the contents of a build log to the browser.  I then add a target into my TFSBuild.proj file that sets the log location to be the http url rather than the default UNC address.

LogView ASP.NET Page

I am by no means an ASP.NET expert - so please feel free to highlight any glaring stupidity on my part if you know better.  I know the code below is sub-optimal and presents some security considerations, however it is a quick work-around that I spent a couple of minutes over to solve my issue - so please treat this code as just that.

Create a new Web Application Project, with references to Microsoft.TeamFoundation.Client and Microsoft.TeamFoundation.Build.Client assemblies.  Create a new aspx page - mine is called view.aspx.  In the page mark-up, ensure it only contains the Page tag, and an output caching directive.  Mine (which is in a C# project) looks like this.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="view.aspx.cs" Inherits="LogViewer._Default" %>
<%@ OutputCache Duration="2592000" Location="Server" VaryByParam="*" %>

Now - the work is performed in the code behind.  

  1 using System;
  2 using System.IO;
  3 using Microsoft.TeamFoundation.Build.Client;
  4 using Microsoft.TeamFoundation.Build.Common;
  5 using Microsoft.TeamFoundation.Client;
  7 namespace LogViewer
  8 {
  9     public partial class _Default : System.Web.UI.Page
 10     {
 11         protected void Page_Load(object sender, EventArgs e)
 12         {
 13             Response.Write("<html>");
 14             string teamFoundationServerUrl = Request.Params["TeamFoundationServerUrl"];
 15             string buildUri = Request.Params["BuildUri"];
 17             if (String.IsNullOrEmpty(teamFoundationServerUrl))
 18             {
 19                 teamFoundationServerUrl = "http://localhost:8080";
 20             }
 22             if (String.IsNullOrEmpty(buildUri))
 23             {
 24                 Response.Write("<title>LogViewer Error</title><body>A valid BuildUri must be passed</body></html>");
 25                 Response.End();
 26                 return;
 27             }
 29             TeamFoundationServer tfs = new TeamFoundationServer(teamFoundationServerUrl);
 30             IBuildServer buildServer = (IBuildServer) tfs.GetService(typeof(IBuildServer));
 32             IBuildDetail buildDetail = buildServer.GetBuild(new Uri(buildUri));
 34             String logFile = Path.Combine(buildDetail.DropLocation, BuildConstants.BuildLogFileName);
 36             Response.Write("<title>Build Log: " + buildDetail.BuildNumber + "</title><body>\r\n<pre>");
 38             StreamReader reader = File.OpenText(logFile);
 39             String line = reader.ReadLine();
 41             while(line != null)
 42             {
 43                 WriteLine(line);
 44                 line = reader.ReadLine();
 45             }
 46             reader.Close();
 48             Response.Write("</pre></html>");
 50             Response.End();
 52         }
 54         private void WriteLine(string line)
 55         {
 56             line = Server.HtmlEncode(line);
 57             if (line.StartsWith("Target &quot;"))
 58             {
 59                 line = "<strong>" + line + "</strong>";
 60             }
 61             Response.Write(line);
 62             Response.Write("\r\n");
 63         }
 64     }
 65 }

As you can see - this is a very quick and dirty example.  I am relying on the output caching of the ASP.NET page to provide any performance at all, and this code could be improved in many ways.  However to walk you through the code;

I start by checking for a TeamFoundationServerUrl parameter, if not passed, I assume that this application is being installed on the TFS server itself so localhost:8080 will get me there. I show an error if the BuildUri is not passed.  Inside the TFSBuild.proj file execution, the MSBuild properties $(TeamFoundationServerUrl) and $(BuildUri) are accessible and provide you all you need to be able to get how of the build that you are building.

Line 29 is me getting hold of the TFS instance, line 30 the build server and finally line 32 the build that I am currently executing.  3 lines to get everything I need to be able to query and modify the build information - you gotta love the TFS2008 build API ;-)

I then (line 34) get the build log path, which is always a file called BuildLog.txt in the drop folder.  I then simply stream the file, line by line, into the response stream.

The WriteLine method is used to do this so that I can optionally do a bit of formatting to the lines as I stream them to the client.  In this example, I am highlighting and lines that are the beginnings of a Target - just to make the log easier to read.

I then deploy this ASP.NET page onto an IIS server.  In my case, I have it running on my production TFS server as a separate application (on a different port) and I have the application set to run as a defined user that has read access to the drop share along with read access to the TFS Build Store.  This means that anyone inside the network can anonymously access the web page and view the build log of any build - but that is acceptable in my organization.  You might want to make access more secure - but then you will also have to be cleverer in your output caching decisions.

TFSBuild.proj File Customization

In the TFSBuild.proj file, I then override one of the provided hook targets to set the log location property of the build.  I'm still un-decided as to which is the best target to put this in, but at the moment I'm going with BeforeGet.

<Target Name="BeforeGet">   <SetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)"      BuildUri="$(BuildUri)"      LogLocation="http://tfsserver:9090/logs/view.aspx?BuildUri=$(BuildUri)" /> </Target>

As you can see - it is pretty low tech, but very effective.  Clicking on the link starts providing me with log output with-in a second.

I actually have the web site running on port 9090 configured to give me directory browsing of the drop location file share (that is also located on the same server).  This means that I can access my drop files using a browser by browsing to http://tfsserver:9090/ - however, you can not update the drop location of the build to be a http:// url.  This is because the drop path is specified (and verified) as a UNC path and several parts of code in the build client API itself assume this.  You could work around this by extending the ASP.NET page mechanism above to provide access to the files in the drop location - perhaps a future project for me ;-)

Rather a lengthy post this one - but I hope it helps someone else out of the same frustrations I was having.  If you've read this far than I guess it was moderately interesting to you :-)

Brian Keller has posted a great interview with Brian Harry about Visual Studio Team System 2008, and a lot of detail on the improvements in Team Foundation Server 2008.  One of the things that I enjoy about talking with Brian Harry is that you get the information in a direct and clear way, with a complete absence of "marketing speak" or buzzword bingo.  At just over 10 minutes in length, this interview is a classic example of that and is densely packed with information - highly recommended.

iTunes Freezing on Close


I swear, one day I'll learn.  Despite having promised myself to steer clear of the initial release of any Windows version of iTunes because they are consistently broke in some pretty severe ways - I read this report on Engadget and decided to upgrade thinking that they may finally haved solved the issues I have been having.  (My main one being that I could consistently crash iTunes on any PC by downloading a podcast and pressing the "pause" button during the download).

However, iTunes 7.6 gave me a great new issue - iTunes wouldn't close.  Every time I tried to close it (by pressing the X button, or doing File, Close) it would freeze and start consuming as much of my CPU as possible - the only way to get rid of it was to kill the process in Task Manager.

Anyway - after a bit of playing, I eventually figured out that this was something wrong with how they are calling Bonjour.  iTunes has the ability to listen for other shared libraries and to share your own library - which is something I had enabled so that I could stream stuff off my laptop onto the Mac Mini and vice-versa.  It does this using Apple's Bonjour service.

On my system, the Bonjour service is installed under the catchy name of


Very user friendly - I think I'll start using GUID's for all my user interfaces :-).  Anyway.  If I stop this service, I can close iTunes down happily.  It will even now let me go into the preferences in iTunes and disable sharing - something that was locking up iTunes 7.6 before (and what made me suspect the Bonjour integration).

Therefore - if you are having the same problems as me, right click on My Computer and select Manage.  Then go to Services and Applications, Services, select "##Id_String1.6844F930_1628_4223_B5CC_5BB94B879762##" and press "Stop".  Then right click, select properties and change the Start-up type from "Automatic" to "Disabled".

This obviously removes the sharing capabilities - but at least it allows you to sync your iPod.  When I finally got iTunes 7.6 to actually work a little bit, I was unsurprised to see that they have still not fixed the bug with the download manager, so if you attempt to do anything to a downloading purchase, podcast or whatever then it will still crash iTunes and will consume most of the available CPU while downloading.  Sigh.

Update:People are reporting that this same issue is true with iTunes 7.6, 7.7 and 7.7.1 so I've removed the version number from the title of this post. Luckily now that I've disabled Bonjour and sharing things seem to be working better for me so hadn't noticed myself that this was the case. Additionally, if you have ESET NOD32 Antivirus installed then you might want to look at this forum post.

Microsoft Team Foundation Server 2008 has a great new improved build system (often referred to as "Team Build").  An advantage of running your build from Team Build is that (by default) all changes between your current build and the last good one are reported in the build report and any work items that were associated with those changesets are automatically updated with the build number they were fixed in.

However, when demonstrating this feature - the following thing always catches me out and is important to remember when using Team Build in production.  The very first time you run a build, it does not associate that build with changesets or update any work items.

Therefore, the first time your create a new build definition you should manually run a build and make sure it is successful. 

In fact I would recommend you do this anyway, even if the changeset association thing wasn't the case, after all you need to test that the new build definition you created actually works!

The reason why Team Build 2008 works in this way is that when Team Build successfully completes a build it stores the label applied to that last good build.  The next time it runs a build that is successful it will compare the two labels to detect which changesets were included in the build.  It will then look over those changesets for any associated work items and update them to include the build number in which they were fixed.

This tip is also true if you upgrade from TFS2005 to TFS2008.  Once the upgrade is complete you should run your builds once manually to check that they are all still working fine and to give a baseline from which changes can be detected.

I just noticed that on Wednesday January 16th at 5pm, the Minnesota Visual Studio Team System User Group are having a talk by Mac Noland.

Mac is a good guy with some very interesting real-life experience in the use of TFS, and I would expect this talk from Mac to give people a great understanding of TFS could fit in their enterprise - but also a realistic, unbiased, warts and all view of TFS with Teamprise in the real world. 

Should be fun - I wish I was closer as I would love to attend myself.  If you are in the area and can make it along, then here are the details:-

Date / Time: Wednesday, Janurary 16th @ 5pm

Where: Microsoft, 8300 Norman Center Dr., Suite 950, Bloomington, MN 55437

Topic: Thomson's use of Team Foundation Server with Teamprise as a cross platform, integrated Configuration Management solution.


Thomson's Online Services is responsible for the backend storage and retrieval of online assets.  The Online Services - Quality department has implemented Team Foundation Server (TFS) for the group, which primarily develops in Java on Windows, Linux, Linux64, Unix and Mac.  With the help of Teamprise, Online Services is now able to interact with their configuration management solution (i.e. TFS) from non-Windows environments. 

Online Services has learned some valuable "cross platform" lessons while implementing TFS.  These lessons may benefit others as they start to implement TFS for non-Microsoft development groups.  A sampling of their experience is below.

  • Yes, you can use TFS to store non-Microsoft software assets
  • Replace multiple bug, change, source management tools with TFS
  • Use Team Build for non-Microsoft builds

Team System MSDN Media Arrives

VSTS 2008 MSDN Media It's funny, in these days of digital distribution, but seeing some physical media for a software project you have been closely involved with still means a great deal. 

Today my January MSDN shipment arrived in the mail - and lo and behold in included a proper physical DVD for Visual Studio 2008 Team System Team Suite.  While it isn't as exciting as a full retail box - it still brought a smile to my face on a foggy morning (sad, I know).

Looks like the folks in the DVD plant have been busy over the holidays.  Congratulations to the Team, lovely to have a real DVD in my hand.


Creative Commons License
This blog is licensed under a Creative Commons License.