During a trial-migration of TFS, I typically prepare a lot of command-line tools to run some background update processes. Instead of writing little C# command-line applications in Visual Studio, I’m moving more and more away from Visual Studio and do stuff via PowerShell.
For a migration upgrade from TFS 2010 to TFS 2013, I have to deal with an update of the Build Controller to a new build machine/server. For a Team Project Collection of 100+ Team Projects and lots of build definitions, this is not something you want to do manually or delegate to all involved dev teams.
Instead of having to start from zero, I found this interesting post from Daniel Mann which does exactly what I want: updating the Build Controller from PowerShell via the TFS API. Except, it does it specifically for one dedicated Team Project.
So, the PowerShell script only needed a bit of tweaking to fetch all available Team Projects via the ListAllProjects method of the ICommonStructureService interface.
param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $TfsUrl, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $NewBuildController, [Switch] $WhatIf ) Function SetBuildControllerForTeamProject($TeamProject, $BuildController, $WhatIf) { $buildDefinitions = $buildClient.QueryBuildDefinitions($TeamProject) $buildDefinitions | % { Write-Host " >> Checking Build Definition" $_.Name Write-Host " >>" $_.Name "is using" $_.BuildController.Name if ($_.BuildController.Uri -ne $controller.Uri) { Write-Host " >>> Setting" $_.Name "to use $BuildController" if (!$WhatIf) { $_.BuildController = $controller $_.Save() } } else { Write-Host " >> Build controller is already set. Taking no action." } } } add-type -Path 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Common.dll' add-type -Path 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Client.dll' add-type -Path 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Build.Client.dll' $tfsUri = new-object System.Uri $TfsUrl $tpc = new-object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection $tfsUri $buildClient = $tpc.GetService('Microsoft.TeamFoundation.Build.Client.IBuildServer') $commonStructure = $tpc.GetService('Microsoft.TeamFoundation.Server.ICommonStructureService') $controller = $buildClient.GetBuildController($NewBuildController) $allTeamProjectInfo = $commonStructure.ListAllProjects() $sortedTeamProjectInfo = $allTeamProjectInfo | sort-object { $_.Name } foreach($teamProjectInfo in $sortedTeamProjectInfo) { Write-Host '************** Scanning Build Definitions in Team Project' $teamProjectInfo.Name SetBuildControllerForTeamProject $teamProjectInfo.Name $NewBuildController $WhatIf Write-Host '' }
You may also use the Community TFS Build Manager (Visual Studio 2013 extension) to modify a number of Build Definitions in bulk, but for my migration scenario, I preferred to have a PowerShell script. Having this script also allows me to modify other settings in the Build Definitions … for example the Build Drop Location.