Programmatically use a server as the Build Server for multiple Project Collections
Posted
on Ewald Hofman
See other posts from Ewald Hofman
Published on Thu, 25 Nov 2010 14:41:13 +0100
Indexed on
2010/12/29
18:00 UTC
Read the original article
Hit count: 753
Important: With this post you create an unsupported scenario by Microsoft. It will break your support for this server with Microsoft. So handle with care.
I am the administrator an a TFS environment with a lot of Project Collections. In the supported configuration of Microsoft 2010 you need one Build Controller per Project Collection, and it is not supported to have multiple Build Controllers installed. Jim Lamb created a post how you can modify your system to change this behaviour. But since I have so many Project Collections, I automated this with the API of TFS.
When you install a new build server via the UI, you do the following steps
- Register the build service (with this you hook the windows server into the build server environment)
- Add a new build controller
- Add a new build agent
So in pseudo code, the code would look like
foreach (projectCollection in GetAllProjectCollections)
{
CreateNewWindowsService();
RegisterService();
AddNewController();
AddNewAgent();
}
The following code fragements show you the most important parts of the method implementations. Attached is the full project.
CreateNewWindowsService
We create a new windows service with the SC command via the Diagnostics.Process class:
var pi = new ProcessStartInfo("sc.exe")
{
Arguments =
string.Format(
"create \"{0}\" start= auto binpath= \"C:\\Program Files\\Microsoft Team Foundation Server 2010\\Tools\\TfsBuildServiceHost.exe
/NamedInstance:{0}\" DisplayName= \"Visual Studio Team Foundation Build Service Host ({1})\"",
serviceHostName, tpcName)
};
Process.Start(pi);
pi.Arguments = string.Format("failure {0} reset= 86400 actions= restart/60000", serviceHostName);
Process.Start(pi);
RegisterService
The trick in this method is that we set the NamedInstance static property. This property is Internal, so we need to set it through reflection. To get information on these you need nice Microsoft friends and the .Net reflector .
// Indicate which build service host instance we are using
typeof(BuildServiceHostUtilities).Assembly.GetType("Microsoft.TeamFoundation.Build.Config.BuildServiceHostProcess").InvokeMember("NamedInstance",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.SetProperty | System.Reflection.BindingFlags.Static, null, null, new object[] { serviceName });
// Create the build service host
serviceHost = buildServer.CreateBuildServiceHost(serviceName, endPoint);
serviceHost.Save();
// Register the build service host
BuildServiceHostUtilities.Register(serviceHost, user, password);
AddNewController and AddNewAgent
Once you have the BuildServerHost, the rest is pretty straightforward. There are methods on the BuildServerHost to modify the controllers and the agents
controller = serviceHost.CreateBuildController(controllerName);
agent = controller.ServiceHost.CreateBuildAgent(agentName, buildDirectory, controller);
controller.AddBuildAgent(agent);
You have now seen the highlights of the application. If you need it and want to have sample information when you work in this area, download the app
TFS2010_RegisterBuildServerToTPCs
© Ewald Hofman or respective owner