Recently in TFS Top Tip Category

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.

If you are customizing a team build, then there are only two things you need to know to get you started.  The rest you can (mostly) figure out from there.

  1. Your build is defined in a file called TFSBuild.proj for your particular Team Build Type.  You probably figured that bit out already.  The first thing you need to know is that the TFSBuild.proj file inherits most of its logic from a file called Microsoft.TeamFoundation.Build.targets which lives in
    %ProgramFiles%\MSBuild\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets.
    If you open this file in Notepad you can see that it is exceptionally well commented.  There is no smoke and mirrors with Team Build, if it happens at all then it triggered by this file. Note that you should never edit the Microsoft.TeamFoundation.Build.targets file.  In Team Build 2008 there are so many hook points provided for you to insert your own logic into the build that you should never need to.  Microsoft goes to some rather extreme lengths to ensure backwards compatibility with this file (i.e. a TFSBuild.proj file written with the TFS2005 targets file in mind will work just great with the 2008 targets file).  If you modify the targets file, not only are you setting your self up for deployment nightmares but you servicing nightmares as well if you attempt to upgrade to later version or even possibly service packs - don't say I didn't tell you ;-)
  2. If you get a bit lost in reading the targets file - the MSDN help for build customizations is pretty good.  The best starting point is the page "Understanding Team Foundation Build Configuration Files" - however the pages that this links to that I refer to constantly are Customizable Team Foundation Build Targets and Customizable Team Foundation Build Properties.  That said - most of the comments in those MSDN help pages are actually in the targets file itself - just sometimes the property or task you are after is easier to find in the MSDN help.

With Team Build in Team Foundation Server, you can have multiple build types for multiple projects.  For example, we have a build that runs fast that we can have running Continuous Integration on, and a slower build (that does obfuscation, release packaging etc) that is run on demand when we want to perform a release to QA (some of which later go on to become public releases).

A neat feature in the Team Build stuff is that you specify a drop location for your builds and the packaged binaries along with the build log and test results will be placed in a folder corresponding to the build name.  In all the demos you see, this will typically be specified as something like \\server\drop and you may well do this yourself at first.  Pretty quickly the drop folder will fill up with builds and get confusing.

A better way is a rather simple solution that I almost didn't mention, however when I mentioned this to a friend of mine and it caused some head-slapping, so I thought I'd discuss it here.  Apologies if you'd already figured this out this rather basic step.

Simply, put your builds into folders.  Something like:-

  • \\server\drop\product\buildType\

To give an example:-

  • \\jeeves\drop\teamprise\ci
  • \\jeeves\drop\teamprise\release

You can obviously take this further if need be.  For example we currently have builds going on in two main places, we are putting Teamprise 2.2 through final testing while, in parallel, we work on the next major release in trunk.  In the example above, it means we have 4 builds types in total and can follow the convention of \\server\drop\product\branch\buildType to make:-

  • \\jeeves\drop\teamprise\2.2\ci
  • \\jeeves\drop\teamprise\2.2\release
  • \\jeeves\drop\teamprise\trunk\ci
  • \\jeeves\drop\teamprise\trunk\release

 Pretty simple really, but helps to plan this stuff up front.

If (like me) you are using the tf.exe command line to access your Team Foundation Server via a Version Control Proxy from a remote office, then the following tip is extremely useful - much more so than my previous registry hack

There is currently no option with the Microsoft command line to pass a version control proxy server in to TF.exe.  It will pick one up if you have one set in the registry if you have used the Team Explorer GUI - but that isn't great for scripted scenarios.  James Manning recently pointed me in the direction of an undocumented environment variable called TFSPROXY.  If set, the TFS client will use that setting to proxy your requests.  Therefore the following will call tf.exe passing a proxy server to use in your connection:-

@echo off
setlocal
set TFSPROXY=http://your_proxy_server:8081
tf %*
endlocal

I saved this in a batch file called "tfvp.cmd" (for "tf via proxy"), therefore if I want to call tf via my proxy and I'm in a shell that doesn't have the environment variable set I can call my script.

The only command that this really useful for is when doing a tfs get command, as only the download is sent via the version control proxy server, the majority of requests go direct to the main Team Foundation Server application tier that you are connected to.

By the way, if you are using the Teamprise command line client then you can use the /proxy:http://your_proxy_server:8081 argument to specify a proxy server to use for the connection, I've just logged a bug so that we will also accept this undocumented environment variable, but we'll make it so that passing one explicitly will override any picked up from the environment variable.

One of the questions that came up from one of our users was "how do I delete the files from my local file system - and tell Team Foundation Server that I have done this".

The first thing you might try is to just delete them locally.  However, Team Foundation Server (TFS) uses your workspace to keep track of what files you have downloaded and what version you have of them.  The reason it does this is so that it can maintain your files without a costly (both in terms of network and CPU processing) sync step.  With TFS, when you say "Get latest", you only get the latest version of files that have changed since you last got them.  Nothing is downloaded that you don't need (thereby saving you network traffic).  A really neat thing about TFS is that if you delete a file on the server and check that delete in, then when somebody does a "Get Latest", the file is deleted on their local system as well - very nice.  Moves and renames also exhibit this behavior - really useful for keeping the local file system in sync with the servers. 

But, if you have deleted a file locally (using Windows Explorer for example) then do a "Get Latest" the file is not downloaded - because the server thinks you already have it.  You can easily download the file by going to "Get Specific Version..." and selecting the "Force get" option - which will download all files, regardless of if the server things you have them or not.

The question I was asked was how to tell the server you have removed the file from your system, without deleting it from the server.  In the end, it took me a while to figure out the answer (and the help of Buck Hodges)

The Get Specific Dialog with changeset 1 inside.

The answer is, if you do a "Get Specific Version..." on the files, and select Changeset 1, the files will be deleted locally and the server will know this.  The color of the file in the Source Control explorer will go from black to gray and will have the phrase "Not downloaded" in the latest column.

Changeset 1 is a special changeset on your Team Foundation Server instance.  It was created as part of the setup routine and only contains one thing - the root node ($/) in your source control tree.  If you do a get for changeset 1 on any actual files then they will not exist at that point in time on the system so will be deleted locally and the server will know this.

Anyway, I thought this worthy of a TFS Tip post.  Not only because it highlights how to do something that is non-obvious, but also because once you understand how it works, you will understand a large part of what you need to know about Team Foundation Server Source Control.

Team Foundation Server source control has a great feature called Shelving.  Shelving lets you set store a batch of pending changes onto the server and optionally remove them from your local workspace.  It comes in really handy for the times when you want to backup your code and store it on the server but don't want to commit it to source control.  I also sometimes use it when I would like a remote colleague to take a look at some code I have written before I commit it into the code base.  For more information about Shelving, see the MSDN documentation.  A Shelveset is identified by developer and the name the developer gave it when shelving.

One of the features of shelving (and how it differs from working in a private developer branch) is that a Shelveset is in itself not versioned.  If the same developer saves a Shelveset with the same name, then it will overwrite the previous Shelveset.  This comes in really handy when you have a Shelveset that you commonly use for one thing - for example, I have a Shelveset that I normally call "Work In Progress" (actually, I normally call it "wip" because I am lazy when it comes to typing, but you get the idea).  If I need to stop work, but I haven't been able to get to a point where I can check-in the code, then I shelve the pending changes and call the Shelveset "Work In Progress".  That way, I only have one of these and I know the purpose of it.

However, most of the time when you shelve, it is a temporary thing.  You create a Shelveset and then you unshelve it - and then you no longer want it.  The old shelvesets will sit on your shelf gathering dust until you tidy them up by deleting them.  The unshelve dialog has a "Delete" button that you can use to delete a particular shelveset.

Additionally, if you press "Details", then you get to see more information about the shelveset in question - but you also get a couple of other options controlling the behavior that occurs while the unshelve is being performed:-

If you un-check the "Preserve shelveset on server" check-box then your shelveset will be automatically deleted after you successfully unshelve it - which is a quite handy (if slightly hidden) feature.

It's good practice to delete the shelvesets when you no longer need them.  Not only will it get rid of clutter for you, it will also help when another person is trying to unshelve something that you have placed there for them.

So, this isn't exactly original material - but I was having a chat with somebody today who I consider very knowledgeable about Visual Studio Team System and they were not aware of these so hopefully re-posting some will help more people discover them.  Strictly speaking, as all of these have been mentioned somewhere before the word "Secret" isn't correct - however it gave an otherwise very dull post a certain bit of excitement which kept you reading this far so forgive me.  The usual Caveats about messing with the registry apply, also the default settings are generally more logical to new users so use with caution.  Most of these tips apply to HKEY_LOCAL_MACHINE as well as HKEY_CURRENT_USER - I normally set them as a user preference so as not to confuse anyone else that should happen to use my machine.

Hack #1 - Stopping Team Explorer from connecting on Visual Studio 2005 Start-up

Add a DWORD value called "AutoLoadServer" under HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\TeamFoundation.  Zero means do not reconnect automatically.

I first read about this setting over at Tim Noonan's blog.  This can be very handy if, like me, you frequently change TFS servers.  I jump between the work TFS instance, CodePlex and a test or VPC versions of TFS.  I know which server I want to connect to when starting VS 2005, and frequently it is not the one I connected to last time.  Adding the following setting means that I have to manually pick the server I want to connect to from the "Add Existing Project..." button.

Hack #2 - Don't get Missing Files

Add a DWORD value called DisableGetMissingFiles under HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\TeamFoundation\SourceControl.  Any value other than zero will disable getting files from the server automatically.

Another Tim Noonan special.  This setting determines if files missing from the solution or project are automatically downloaded.  I normally switch this off and so get the files only when I say "Get Latest" on a particular solution or project, this is especially useful when you are not always connected.

Hack #3 - Bypass proxy server

Add a String value called BypassProxyOnLocal under HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\TeamFoundation\RequestSettings.  A value of "true" will bypass.

This one from the legendry Buck Hodges.  In some network configurations, the Microsoft Team Foundation Server client will connect to your Team Foundation Server via a web proxy server.  This should be avoided as it slows everything down and the NTLM authentication used by TFS doesn't play well with some proxy configurations.  I've seen this pop up as a problem with environments that use a proxy.pac file to control proxy access rather than hard-coding the entries in the Internet Options, LAN Settings (or for folks that don't have Bypass local set up).  You should probably only use this setting if you know you are having this problem (often diagnosed by an intermittent failure of Team Explorer to connect but easily checked using a network sniffing tool such as Ethereal).

Hack #4 - TFS Version Control Proxy Settings

See HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\TeamFoundation\SourceControl\Proxy.  A String value called Url containing the proxy address and a String value called Enabled set to true will enable the source control proxy.

The easier way to enter values for what machine to use as a TFS Version Control Proxy is to go to into Visual Studio with Team Explorer installed and select Options, Source Control, Tools, Options, Source Control, Visual Studio Team Foundation Server, Proxy Settings.  However, if you are running a tf.exe script or TFS .NET API code as part of a service and you want the code to go via a proxy then the HKEY_LOCAL_MACHINE version of this setting is very useful for setting a default.

Hack #5 - Configuring the TreeDiff Power Toy

See Brian Harry's excellent post about some registry tweaks for Configuring the TreeDiff Power Toy to your whim.

Archives

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