Configuring Multiple TFS Build Services on one Machine

In TFS 2010, the Build Service is a Windows Service that is associated with a particular TFS Team Project Collection. Each Build Service support zero to one (0..1) Build Controllers and zero to n (0..n) Build Agents. Each Build Agent is associated to a specific Build Controller but an Agent and its corresponding Controller don’t need to be on the same machine. This topology lets you configure a continuous integration build that queues its builds on the Build Controller you’ve specified which then farms out the heavy lifting to any of the n agents it manages. This gives you an easy way to load balance your builds across a set of machines.

There is a potential down-side, however, in that each build service can only service one particular project collection. In TFS 2005 and 2008, a build agent was configured for a particular Team Project and you could only run one Build Agent per machine (though you could manually configure the same build agent for multiple Team Projects on the same server. Since you can have multiple Team Projects in a single Team Project Collection, the configuration experience has definitely improved in TFS 2010. That said, you may still find yourself needing to provide build services for multiple Project Collections from a single build machine. While I don’t recommend using this as a production configuration, it may be useful if you’re juggling multiple Project Collections on a machine that you’re using for demonstration purposes.

Note: this is not a supported configuration of the TFS Build Service – use it at your own risk.

  1. Open a Command Prompt window as Administrator on the build machine.

  2. Use the command line interface to the Service Control Manager to setup a second named instance of the Build Service.

    E.g. sc.exe create buildMachine-collection2 binpath="C:\Program Files\Microsoft Team Foundation Server 2010\Tools\TfsBuildServiceHost.exe /NamedInstance:buildMachine-collection2" DisplayName="Visual Studio Team Foundation Build Service Host (Collection2)" Note: For TFS 2012, you'll need to use the corresponding path to the executable.

    We recommend including the Project Collection name in the display and instance names for this second instance of the Build Service to make it easier to determine which instance you’re managing.

  3. Set the TFSBUILDSERVICEHOST environment variable to refer to the new instance of the Build Service you just created by setting its value to the string you passed in the NamedInstance parameter in step 2. Note: For TFS 2012, the environment variable name is TFSBUILDSERVICEHOST.2012.

    E.g. set TFSBUILDSERVICEHOST=buildMachine-collection2

  4. Start the Team Foundation Administration Console from the same command prompt so that it gets the environment variable you just set.

    E.g. "C:\Program Files\Microsoft Team Foundation Server 2010\Tools\tfsmgmt.exe"

  5. Ensure that the new Build Service instance has a TFS resource Uri that is distinct from the originally configured Build Service. You can view the Uri in the Uri value under the following registry key:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\TeamFoundation\Build\tfsbuildservicehost1

    If the Uri is the same as the one under the Build\ServiceHost registry key, you’ll need to unregister the new Build Service instance and re-register it. To do so, first you’ll need to create a new Controller or Agent for the new Build Service instance in the Team Foundation Administration console. Next, you’ll need to click Unregister to unregister the Build Service and delete its associated Controller and/or Agents. When you re-register it, it should get a new Id that won’t conflict with the originally configured Build Service instance.

  6. Ensure that the new Build Service instance is configured to listen on a different port than the originally configured Build Service. You can do this by opening the Properties dialog for the Build Service and changing the port appropriately.

  7. If you’re working in a demo environment and the project collections you’re configuring Build Services for are starting out in the same state, there’s a good chance that, if you configure a Build Controller for each of the two Build Service instances, the Build Controllers will both end up with the same Id due to the way the TFS database auto-increments identity columns. This is only an issue if you use the custom assembly path for both Build Controllers and they use a potentially conflicting set of content in that path. If that’s the case, you can remove one of the Build Controllers from one of the Build Service instances, then recreate it and it should get a different Id.

  8. Update default working directory for the agents you create on each Build Service instance. If you don't, there’s a chance that two Build Agents (one under each Build Service instance) will have the same Id and, consequently, the same working directory. Update the working directory in the Agent Properties dialog to include the collection name or some other distinguishing element. E.g. $(SystemDrive)\Builds\$(BuildAgentId)_Coll2\$(BuildDefinitionPath).

  9. If you’re using (or plan to use) the new Symbol Server integration features in TFS 2010, you’ll need to setup a separate Symbol Store for each Team Project Collection. Symbol Server does not support concurrent storage access. TFS Build handles this by synchronizing access to the Symbol Stores used within a given Team Project Collection. This synchronization doesn’t work across Collections, however, so you’ll need to maintain separate Symbol Server stores for each Collection – fortunately, this is just a shared directory.

  10. Ensure that the drop folders used in the Build Definitions across Project Collections are different. In most cases, this won’t be a problem unless two projects have same name across Project Collections.

  11. Before installing TFS hot-fix or service pack, please stop all Build Service instances manually from Service Control Manager and restart them after patch installation is successful.

When you’re done, you’ll have a single machine that is providing Build Services for two separate TFS Team Project Collections. If you want to run builds on both Build Service instances concurrently, you’ll want to take steps to prevent resource contention like moving the working directories for the Agent on one of the instances to a separate hard disk. Even then you may encounter serious performance degradation if two instances of MSTest are invoked at the same time.

Let me reiterate that this is a hack and is not a supported configuration of TFS Build 2010. If you believe you have legitimate need to apply this configuration to a production build environment, contact me and describe your scenario in detail.