TFS & MSBuild Part 1 (update code)

18Oct06

Voila, my first blog post! It’s about time I throw some stuff up online. Let’s get right into it…

I work in an environment where we are running multiple development copies of a web application at a time (with different configurations). Up until now, when a new stable version is complete I have had to open up each solution file for this application in Visual Studio and right-click-’get latest’ then compile. Faster to use a single click of a custom MSBuild script to automatically do a “get latest” of code from TFS source control and then compile on the command line. You could then use MBuild to run unit tests or whatever other processing tasks are required.

This script uses calls to tf.exe (command line tool for TFS) and devenv.exe (command line for visual studio) to do the work for me.

1. Create a new text file called UpdateProject.csproj. The ‘.csproj’ extension is used by MSBuild (you’ll recognise the extension because Visual Studio 2005 project files are really just MSBuild configuration xml).

2. Copy the following into it and edit your settings appropriately

<Project xmlns=http://schemas.microsoft.com/developer/msbuild/2003>
<!–

this is an msbuild script that creates a temporary workspace, gets latest code, and compiles it.
This helped a lot: http://blogs.msdn.com/manishagarwal/archive/2005/12/06/500440.aspx

you can override the properties by passing them at the command line:
msbuild getlatestsource.xml /p:solutionroot=”c:\inetpub\site1″ /p:Workspacename=Site1

current limitation: unable to get the
working on this:
tf workspaces /server:http:tf1:8080 SAH /owner:* /format:detailed
//then deleting the workspace using the output from that.
–>
<
PropertyGroup>
<!–
name of TFS server–>
<
ServerName>http://tf1:8080</ServerName>

<!– operating folder–>
<
SolutionRoot></SolutionRoot>
<
SourceControlMainDirectory>$/MyTFSProject</SourceControlMainDirectory>
<
WorkspaceName>MyWorkspace</WorkspaceName>

<!– Path to command line tool–>
<
TfCommand>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\tf.exe</TfCommand>
<
DevenvCommand>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv</DevenvCommand>
<
WorkingDirectory>c:\</WorkingDirectory>
</
PropertyGroup>

<Target Name=GetLatest>

<Exec Command=$(TfCommand) workspaces /server:$(ServerName) $(WorkSpaceName) /owner:* WorkingDirectory=$(SolutionRoot) ContinueOnError=true />

<Exec Command=echoIt’s not simple to delete another user’s workspace dynamically. If this folder is mapped to another user, the following commands will fail until that workspace is deleted. You can do so using the Team Foundation SideKicks software, or by using the following dos command (only if you have administer workspaces permission on TFS)… tf workspace /delete $(WorkspaceName);[domain]\[username] /server:$(ServerName) WorkingDirectory=$(SolutionRoot) ContinueOnError=true />

<!–Delete existing workspaces, since you can’t create one if one already exists. Unfortunately this will not delete workspace by a different user, which is sort of the point here–>
<
Exec Command=$(TfCommand) workspace /delete $(WorkSpaceName) /server:$(ServerName) /noprompt WorkingDirectory=$(SolutionRoot) ContinueOnError=true />

<!– Recreate main workspace–>
<
Exec Command=$(TfCommand) workspace /new $(WorkSpaceName) /server:$(ServerName) /noprompt WorkingDirectory=$(SolutionRoot) ContinueOnError=false />

<!–Add mappings to the workspace–>
<
Exec Command=$(TfCommand) workfold /map /workspace:$(WorkSpaceName) /server:$(ServerName) $(SourceControlMainDirectory) $(SolutionRoot) WorkingDirectory=$(SolutionRoot) ContinueOnError=false />

<!–Apply Label on workspace - such as ’site1_latest’–>
<
Exec Command=$(TfCommand) labellatest_$(WorkSpaceName) /server:$(ServerName) /recursive /comment:This dev site currently has this version of the code. $/PHX WorkingDirectory=$(WorkingDirectory) ContinueOnError=false/>

<!–Sync files on the local disk. I was using the /force switch but that is too dangerous. Instead, writable files are ignored. I continue on error because otherwise it would stumble over any writable files–>
<
Exec Command=$(TfCommand) get$(SolutionRoot) /recursive /version:T /noprompt WorkingDirectory=$(SolutionRoot) ContinueOnError=true />

<!–We could delete the workspace now, but it might be useful to leave here. That means that if someone opens the solution after running this, they will already have a workspace mapped.–>
<!–
<Exec Command=”$(TfCommand) workspace /delete $(WorkSpaceName) /server:$(ServerName) /noprompt” WorkingDirectory=”$(SolutionRoot)” ContinueOnError=”false” />–>

<!–compile, by simply using the configuration setup in the solution in Visual studio. This just calls visual studio at command line to compile without having to open it.–>
<
Exec Command=$(DevenvCommand) $(SolutionRoot)\EmergeSurvey.sln /build Debug WorkingDirectory=$(SolutionRoot) ContinueOnError=false />

</Target>
</
Project>

3. Now from a Visual Studio command prompt, type msbuild UpdateProject.csproj. Unfortunately this version does not work if another developer already has that location mapped to their workspace. I’m working on a solution to this and will post it when I figure it out. [edit:see the custom MSBuild task I created for this.]

Why not Nant? This example could easily be done in Nant, since I’m just running a bunch of command prompts. I was going to use Nant for this, being a more mature build software, but moved away from it when I discovered that the ‘Solution’ task does not yet work with VS 2005. NAnt ’solution’ task is supposed to run faster than calling devenv.exe using something simple like this:

<solution solutionfile=”MySolution.sln” configuration=”Debug” />.

Hopefully the next Nant release will get this working (someone please post a comment if this has changed). Besides, if I ever need to use NAnt, I can always run this MSBuild csproj from a NAnt task.

Why not TFS Team Build, which is essentially MSBuild with extra TFS tasks? I’ve played with it a bit but just haven’t had the time to completely figure it out. I’ve clicked around using the Team Explorer add-in in Visual Studio. You can right click the ‘Team Builds’ folder and create a new build this way. Supposedly using the TFS Team Build tasks is more reliable, than using TFS command line calls (don’t know why), so it might be worthwhile to figure for me to figure this out. The potential integration with Visual Studio and sharepoint looks really slick.

Some reference links:

2 Responses to “TFS & MSBuild Part 1 (update code)”


Who's linking?

  1. 1 TFS and MSBuild part 2 (batch scripts) at Dylan Marks’ Weblog Pingback on Oct 31st, 2006
    "[...] Archives « Creating Site: TFS and MSBuild [...] "
  2. 2 TFS & MSBuild Part 3 (custom msbuild task) at Dylan Marks’ Weblog Pingback on Nov 2nd, 2006
    "[...] In my first post in this series I showed an msbuild script that would create a Team Foundation Server ..."

Leave a Reply


Comment guidelines: No spamming, no profanity, and no flaming. Inappropriate comments will be deleted outright.

Quote selected text




 

About

My name is Dylan Marks. I'm a programmer and tech consultant focused on web application development, typically using ASP.NET, javascript and web standards-based technologies. I hope to share some of the useful tips and tricks I've discovered while making things work. I live in Edmonton, Alberta, Canada, working remotely for clients across North America. Email Me.