Introduction
Anyone who has managed a software project of any size, and particularly a large web based project, has likely heard a developer describe how the code "worked on my machine", but did not work when rolled out to a testing or production environment. While in many cases these errors could have been corrected if the developer had been more careful, there are enough challenges related to developing software and writing working code without having to worry about whether what was developed and tested is what has been deployed. As software tools continue to grow in complexity, organizations increasingly embrace Service-Oriented and Enterprise Architecture, and the prevalence of large and complicated web based solutions continues to increase, the ability to compile and deploy these solutions in a predictable manner has become a necessity.
Team Build is Microsoft's first out of the box build lab for .NET. While third party tools have allowed developers to create automated builds for several years, Team Build is the first build tool to come integrated with the VS.NET IDE. Team Build's strengths lie in its tight integration with the Visual Studio Team System environment. As such, it is possible to create and execute builds that run unit tests, analyze code for adherence to design standards, generate metrics related to what changes went into the build, who checked them in, how much of the code is tested by unit tests, and what Team System work items were included. Team Build uses and extends upon MSBuild, the new build engine in VS2005 that is used when manually compiling a solution through the VS.NET IDE.
Many of the weaknesses of Team Build lie in the infancy of the product. As a Beta product, it definitely has some rough edges. As of Beta 2, there is not a built-in mechanism for scheduling a build, it lacks the ability to perform continuous integration by executing a build whenever code is checked in, there are few built in tasks compared to other build solutions (although it is possible to write custom tasks using any .NET language), as well as a shortage of comprehensive documentation. It is also difficult to get a variety of its more complicated features to work correctly without knowing a few tricks.
Despite these drawbacks, it is possible for those using Team System based projects to create a sophisticated and powerful build process using Team Build. This article will explore how to use Team Build to build a simple solution, and will gradually explain how to extend this solution to implement a more complicated and automated build process that includes dependencies, unit testing, code analysis, and status notification.
System Requirements
To run the code for this sample you should have:
- A .NET 2005 Team Foundation Server (includes SQL Server Yukon April CTP with SQL Reporting Services) running Windows Server 2003 Standard or Enterprise Edition.
- The .NET 2005 Team Suite client.
Installing and Compiling the Sample Code
An application is used to allow a build to be scheduled and automated. The application is a command line executable that invokes a web service that is used when manually running a build through the VS.NET IDE. As of Beta 2, the ability to schedule a build is only available by writing code to invoke the Team Build web service. A utility is expected to ship with the initial production version that would allow a build to be scheduled without writing custom code.
- Create a new .NET 2005 console application named TeamBuild . Store under C:\Projects\TeamBuild , and do not create a separate directory for the solution.
- Set a web reference to http://<teamserver>:8080/TeamBuild/buildcontroller.asmx .
- Copy the code from the download found in Program.cs replacing all existing code.
- Compile the application and copy to the machine where you want to kick off the build (e.g. the Build server or the Team Server).
Installing Team Build
Team Build is not installed by default as part of the Team Foundation Server installation. Assuming you have met the aforementioned system requirements, the next step in creating an automated build using Team Build is to install the Team Build component. The Team Build installation program can be found on the Team Foundation Server installation disk. I recommend installing Team Build on a dedicated build server or on the Team Foundation Server itself, as opposed to installing on a developer's workstation. The build server should be as similar to the production web server as possible in terms of the OS, installed software, software configuration, etc., in order to reduce of the risk of the deployed software not working in production due to a difference in machine configuration. Using a dedicated build server should result in a more stable build environment than using a developer's workstation that may be periodically rebooted during the day, may have a non-standard configuration, and may compete with other applications and services for PC resources.
To install Team Build:
- Insert the Team Foundation server CD, and run <Drive>:\bb\Setup.exe . NOTE: If installing on a Windows Server 2003 machine, the installation will fail unless the Windows Firewall is turned on, so make sure it is on before proceeding. This issue is present with Beta 2 and is expected to be fixed with the next release.
- Accept all default settings.
Creating a Solution for Use with Team Build
If you have worked with Team System projects but not with Team Build, I recommend against skipping over this section, as a Team Project must be setup in a specific way for the build to be started from a developer's machine. In order to use Team Build, you must first create a Team Project.
To Create a Team Project:
- From the VS.NET IDE, choose File | New | Team Project to launch the new Team Project Wizard (see Figure 1).

Figure 1. Specifying the Team Project Settings
2. Choose the MSF Agile process template (the only template currently available by default) and hit next, continuing to accept the default settings until the Team Project has been created.
In order to run a build from a development client, you will first need to create a separate Workspace for the new solution.
To Create a New Workspace:
- Under File | Source Control | Workspaces …, choose to Add a new Workspace.
- Choose the Repository Folder $/TeamBuildTutorial and Local Folder C:\Projects\TeamBuildTutorial : (see Figure 2)

Figure 2. Editing the Workspace settings
To associate a new solution with this Workspace:
- Create a new blank solution named TeamBuildTutorial and choose a location of C:\Projects (see Figure 3).
- Ensure the Add to Source Control box has been checked, and click OK .

Figure 3. Adding a New Solution
Building a Sample Website
At this point you have a Team Project in place with a local workspace and an empty solution. The next step is to create a simple project that we can use to create a build.
To create a simple web project:
- Add a new C# Web Site to this solution and store it under C:\Projects\TeamBuild\Tutorial\Web .
- Add a Label to the default web form with a caption of " Hello World " so that you can start with a simple solution to build and verify.
- Check the solution into source control so that you can integrate pulling from source control with the build process.
Now that you have a Team Project in source control, you can begin the process of creating a build script. A wizard exists to help you through much of this procedure.
To create a build script for the solution:
- From the Team Explorer, Right-click on the Team Builds folder and choose New Team Build Type… . (see Figure 4).
- Name the BuildType TeamBuildTutorial and provide a description if you so desire (see Figure 5).
- Choose the TeamBuildTutorial workspace and choose to build the TeamBuildTutorial.sln solution (see Figure 6).
- Select to perform a Debug configuration build on AnyCPU . The available configuration options here are the same as when building through the VS.NET IDE (Debug or Release). The Debug configuration allows runtime errors to be debugged, while the Release configuration is more appropriate for a production release. The Release configuration runs faster and does not allow the end user to debug unhandled errors (see Figure 7).

Figure 4. Creating a new Build Type

Figure 5. Entering a Build Type name

Figure 6. Choosing the Solution to build
The Platform option is a more advanced option that will not need to be changed in the majority of cases. If you creating a project that references COM objects and\or uses Win32 API's, and this project could run on a 64-bit processor, this option may need changed. For more information on advanced platform options see the links section.

Figure 7. Setting the appropriate configuration
- Enter the name of the build server where Team Build is installed, and choose C:\Build as the build directory.
- Create a directory named DropLocation on the build server under C:\Build directory. Share this folder as DropLocation (see Figure 8). The account that the VSTF App Pool application pool is running under on the Team Foundation Server (configured when installing the Team Foundation Server), will need access to write to this directory or the build will fail. When implementing a build in a production environment, the actual build and drop location directory names can be chosen based on your network naming conventions, but many build solutions advocate creating a directory named Build , putting all build output under this directory, and ensuring that this directory is backed up.
- Do not set the Run test or Perform code analysis options (see Figure 9). The Run test option allows the build to execute unit tests to verify that the compiled output passes user-defined tests. The Perform code analysis option allows the build to analyze the output for coding standards violations. These options will be set and discussed in more detail later on.
- Review the options you have selected and hit Finish to create a Build Type (see Figure 10). A Build Type is an XML-based file that contains settings such as the build server name, team server name, solutions to build, testing and code analysis options and the other options set through this wizard.

Figure 8. Seting the build location

Figure 9. Setting the build options

Figure 10. Reviewing the build options
At this point you have a fully functional build script for a simple project.
The build output will be copied to a location based partially on the build version number. The version number for a given build is set automatically as:
<BuildTypeName>_YYMMDD.<number of times run that day, with trailing zero's to make four characters>
For example the first build executed on 7/1/05 for a build type named TeamBuildTutorial would have a version number of TeamBuildTutorial_050701.0001 . The build output is placed under a directory with the build version name, so by default each build output will be copied to a unique location.
To execute the build script
- Right-click on the newly created build type from the Team Explorer and choose to build the solution .
- A status window will appear showing the build status (you will have to manually refresh the window to see updates).
- Once the build successfully completes, create a virtually directory on the build server to point to the build output folder at C:\Build\DropLocation\TeamBuildTutorial_<Build#>\Debug\_PublishedWebsites\Web .
- Depending on what applications and .NET Framework versions are installed on your web server, you may need to set this site to run under a non-standard port and/or its own Application Pool.
- Launch this site from a web browser and verify that the Hello World form appears.
Creating and Executing Unit Tests
You now have a build script that compiles and deploys a simple web project, but what if you want to extend this script to add features or additional projects? I will now walk through customizing this build script to work a solution with multiple projects, and more advanced features such as code coverage, unit testing, and code analysis.
To add an additional project
- Add a new class library project ( File | New | Project ) to the solution called Data , under C:\Projects\TeamBuildTutorial (see Figure 11).
- Add a class named Utility to the data project.
- Modify the class to contain the code found below. The TwiceInitialValue() function simply returns a number that is twice the parameter passed in. While a function as simple as this probably wouldn't be found in a real world application, it is included here to help illustrate how to test a procedures output from a unit test. The MachineName property is included to help us identify on which machine our solution is running.

Figure 11. Adding new project
using System;
using System.Collections.Generic;
using System.Text;
namespace Data
{
public long TwiceInitialValue(long initialValue)
{
return initialValue * 2;
}
public string MachineName
{
get { return System.Net.Dns.GetHostName(); }
}
}
To add unit testing to the project:
- Right-click to the right of the Utility class name and choose to Generate Tests . Choose to Create a new Visual C# Test Project… as shown in Figure 12.
- Create a new C# Test project named TeamBuildTest as shown below in Figure 13.
- Modify the test created for you as shown below:

Figure 12. Generating a new unit test project

Figure 13. Entering a test project name
[TestMethod()]
public void DoubleNumberTest()
{
Data.Utility target = new Data.Utility();
long number = 10;
Assert.IsTrue(target.TwiceInitialValue(number) == 20);
}
This test simply verifies that the TwiceInitialValue() function returns a number that is double the value passed in. Typically a good unit test would test an application's business and/or data layer to ensure that business rules are handled correctly, and/or data is accessed successfully. To learn more about writing unit tests with VS.NET 2005 see the links section.
In order to run our test from a build, you need to create a Test List:
- From the Test menu, choose Manage and Execute Tests .
- Under Lists of Tests , right-click and choose to create a new Test List named Build Test List .
- Add the MachineNameTest to this test list.
The build script created for you by the wizard is an XML file that contains instructions for building your solution. At this point, you can no longer use the wizard to modify your build script, but instead must manually edit the build script file. To do this, the Build Type must be checked out of Source Control, but this cannot be done simply by editing the file or right-clicking on it from the Team Explorer.
To edit the Build Type created by the wizard:
- From the Team Explorer, double click on the Version Control folder.
- Ensure the Workspace is set to TeamBuildTutorial or you will not have access to check out the build script.
- Browse to TeamBuildTutorial | TeamBuildConfigurations | TeamBuildTutorial , and check out TeamBuild.proj .
- Open the build script and view its contents. I usually remove the vast majority of comments created by the wizard, as I find them to be mostly noise that interferes with the script readability, and I think the tags are pretty self-documenting.
- Set the <TestingFlag> attribute value to true and set the <TestingArgs> value to: /testmetadata:$(SolutionRoot)\TeamBuildTutorial.vsmdi .
- Add a project reference to the Data project from the web project.
- Modify the default pages load procedure to look as follows so we can verify that the build picked up the new project:

Figure 14. Checking out the Build Type script
protected void Page_Load(object sender, EventArgs e)
{
Data.Utility myUtility = new Data.Utility();
lblMessage.Text = "Hello World from, " + myUtility.MachineName;
}
- Check-in all pending changes (including the build script) to source control and build the solution.
- Once the build completes, double-click on the build from the status window to see detailed build metrics. You should see a section for Test results that shows successful test completion, as shown below in Figure 15. It is also possible to view the changes that went into the build, the individuals who made these changes, and any build errors or warnings from this screen.

Figure 15. Viewing the Build Status
Adding Code Metrics
Now that you can run unit tests as part of the build process, you might as well allow the build to report on how effectively the tests cover the source code. This will show what percentage of source code is being tested by the unit tests and will highlight areas of code that do not have an associated test.
To add test code coverage metrics:
- From the Test menu, choose to Edit Test Run Configurations .
- Select the Code Coverage section and choose to instrument Data.dll from its source location as shown below.
- In order to get this change to be recognized by the build, the . testrunconfig must currently be edited manually to remove the full path to the assembly and only include the assembly name. Right-click on localtestrun.testrunconfig and open with an XML editor.
- Change the binaryFile attribute value from Data\bin\Debug\Data.dll to Data.dll . Check-in these changes and re-build.

Figure 16. Selecting projects for which to report Code Coverage
The next step is to enable code analysis as part of the Build. Code Analysis is performed by FxCop, a tool that has been available for download prior to Beta 2, but is now integrated within the VS.NET IDE. This tool checks code for adherence to .NET Framework design guidelines, and can be customized to exclude certain rules or to include custom rules. To enable FxCop code analysis:
- Check out the build type as described above.
- Change the value of the <RunFxCopFlag> to true .
- Re-run the build and FxCop warnings will appear in the build log. NOTE: There is an issue with Beta 2 that causes the build to fail if your project does not have any FxCop violations.
Deploying a Successful Build to a Static Location
Since successful builds are copied to a directory based on the build's unique version number, many organizations may want to modify the build process to have it copy the last successful build output to a static location so that testers and/or users can always get to the most recent code from the same location. Team Build creates a file called CustomAction.targets in the same directory as the build type, and this file contains placeholders for custom actions to be performed along with the default build events.
To ensure the website created in this tutorial is always copied to the same output location:
- Check out the CustomAction.targets file from Source Control.
- Add the following code after the first line of the file, to specify where the compiled output resides by default:
- Add a new target to the file, to copy the build output to a specific destination folder, that we will call C:\Projects\TeamBuildTutorial . The new target should look as follows:
<ItemGroup>
<MySourceFiles Include=
"$(BuildDirectoryPath)\$(PortfolioProject)
\$(BuildConfiguration)\Binaries\Debug\**\*.*"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy SourceFiles="@(MySourceFiles)"
DestinationFolder="c:\Projects\TeamBuildTutorial\"
/>
- Modify the existing CustomPostBuild target to include a DependsOnTargets attribute with a value of CopyFiles , as shown below. This will run a copy files task when a build completes successfully.
<Target Name = "CustomPostBuild" DependsOnTargets="CopyFiles"/>
The file contains a lot of comments by default, but the full file (excluding comments) should resemble the following when all modifications have been made:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MySourceFiles Include="$(BuildDirectoryPath)\$(PortfolioProject)\
$(BuildConfiguration)\Binaries\Debug\**\*.*"/>
</ItemGroup>
<Target Name = "CustomClean" />
<Target Name = "CustomSync" />
<Target Name = "CustomPostSync" />
<Target Name = "CustomCompile" />
<Target Name = "CustomPostBuild" DependsOnTargets="CopyFiles"/>
<Target Name="CopyFiles">
<Copy SourceFiles="@(MySourceFiles)"
DestinationFolder="c:\Projects\TeamBuildTutorial\"/>
<Target Name = "CustomTest" />
<Target Name = "CustomAnalysis" />
<Target Name = "CustomCopy" />
</Project>
- Create the C:\Projects\TeamBuildTutorial directory.
- Create a Virtual Directory named TeamBuildTutorial that points to this new directory.
- Check the modified .targets file into Source Control.
- Execute the build and verify that is available from the virtual directory you have created.
Scheduling the Build
In addition to reliably deploying solutions, a build also offers the ability to integrate code changes from multiple developers early and often. This helps to catch any integration issues early on and helps to push a development team to achieve quality on a daily basis. Even with small development teams, the ability to track code quality, code test coverage, and ensure the latest copy of code successfully compiles can be of great value. Beta 2 unfortunately does not contain a utility to allow a build to run on an automated schedule, but luckily you take advantage of the Team Build web services to create your own utility.
To automate and schedule the build:
- Ensure the command line executable TeamBuild.exe , created in the " Installing and Compiling Sample Code " section has been copied to the build machine.
- Schedule the application to run under the windows scheduler using the add schedule wizard under Control Panel | Scheduled Tasks on the build machine. The wizard will prompt you to browse to TeamBuild.exe and choose an appropriate schedule (many organizations run a nightly build that occurs late at night when no one is working).
- Command line arguments cannot be added when initially scheduling an item through the add schedule wizard, but once the item has been scheduled, right-click the item to view the task properties, and change the Run textbox to include the executable name and appropriate command line arguments (run Team Build.exe with a /? command line switch to see the available options). If the custom build scheduling executable were located under C:\Build\TeamBuild.exe and the team server and build machine are named TEAMSERVER , the full path to include in the Run textbox would be:
C:\Build\TeamBuild.exe -TFSServer:TEAMSERVER -PortfolioProject:TeamBuildTutorial
-BuildDirectory:C:\Build -BuildMachine:TEAMSERVER
Once a build has been scheduled, it's nice to receive an appropriate alert when the build completes, especially if the build runs during non-working hours.
To Setup Alerts:
- From the Team menu, choose alerts .
- Enter the email address(es) you would like to receive the alerts when the build completes and/or the build status changes.
- Ensure the Team Server has been configured to send email through an appropriate SMTP server.
Conclusion
Team Build is the first build utility built into the VS.NET IDE. It only works with Team System based projects, but does offer a lot of potential in terms of integrating a build process with new VS.NET features such as unit testing, code analysis, and work item tracking. While Team Build offers several powerful features with Beta 2, several of these features are either difficult to implement or require knowledge of appropriate workaround procedures. Many fixes are scheduled for the initial production release that should make working with Team Build much easier. The Beta 2 product is still rough around the edges, but coupled with the knowledge obtained through this article and information found in related links section, you should be well equipped to create a powerful integrated build solution with Team Build.
