How to execute a special build on TFS using Team Foundation Object Model (TFS APIs) – Part 2
Through this tool, those Build and Managers will be able to:
* Select a previous build
* View changesets which are created after that build, with their comments
* Select all or few changesets from the list to be included in the next build
* Label them with a temporary label
* Execute that build
* Finally, associate the selected changesets with the executed build while overriding the default behaviour of the Team Build.
In the first part of the article we have completed the code for selection of Build Definition, Build, Changesets after that build was executed and changesets which need to be considered for the next build. The entire set of code files is uploaded in a project at CodePlex at http://custombuildmanager.codeplex.com .
We have now come to the heart of the program where we will set the label to the files which are either in the base build or are added later on. We will omit build definition folder so that we do not build unnecessary files. Before we label the files we will delete any existing label of the same name.
public void SetLabel(List<int> ichangeSets, string LabelName, string SelectedBuild)
//First get changesets for the build
//for that create an array of items labeled with selected build number
LabelVersionSpec LabelSpec = new LabelVersionSpec(SelectedBuild);
ItemSet LabeledItems = tfvc.GetItems("$/" + project, LabelSpec, RecursionType.Full);
Item items = LabeledItems.Items;
// Now add the latest changeset associated with each item
List<int> csInBuild = new List<int>();
foreach (Item item in items)
//now add changeset numbers passed by parameter ichangesets and remove duplicates if any and sort them
foreach (int cs in ichangeSets)
changeSets = removeDuplicates(csInBuild);
//Create a versioncontrol object
VersionControlLabel labelToCreate = new VersionControlLabel(tfvc, LabelName,
fvc.AuthenticatedUser, "$/" + project, "Demo Label");
//Create labeled items. Remove items which are for build configuration files
List<LabelItemSpec> labelItemsSpecs = new List<LabelItemSpec>();
for (int i = 0; i < changeSets.Count; i++)
foreach (Change change in tfvc.GetChangeset(changeSets[i]).Changes)
ItemSpec changeSetItemSpec = new ItemSpec(change.Item.ServerItem,
labelItemsSpecs.Add(new LabelItemSpec(changeSetItemSpec, new
//Now actually label the items. Remove the exisitng label if any.
LabelResult PrevResults = tfvc.DeleteLabel(LabelName, "$/" + project);
LabelResult results = tfvc.CreateLabel(labelToCreate, labelItemsSpecs.ToArray(),
Public Sub SetLabel(ByVal ichangeSets As List(Of Integer), ByVal LabelName As String, ByVal SelectedBuild As String)
'First get changesets for the build
'for that create an array of items labeled with selected build number
Dim LabelSpec As New LabelVersionSpec(SelectedBuild)
Dim LabeledItems As ItemSet = tfvc.GetItems("$/" & project, LabelSpec, RecursionType.Full)
Dim items() As Item = LabeledItems.Items
' Now add the latest changeset associated with each item
Dim csInBuild As New List(Of Integer)()
For Each item As Item In items
'now add changeset numbers passed by parameter ichangesets and remove duplicates if any and sort them
For Each cs As Integer In ichangeSets
changeSets = removeDuplicates(csInBuild)
'Create a versioncontrol object
Dim labelToCreate As New VersionControlLabel(tfvc, LabelName, fvc.AuthenticatedUser, "$/" & project, "Demo Label")
'Create labeled items. Remove items which are for build configuration files
Dim labelItemsSpecs As New List(Of LabelItemSpec)()
For i As Integer = 0 To changeSets.Count - 1
For Each change As Change In tfvc.GetChangeset(changeSets(i)).Changes
If (Not change.Item.ServerItem.Contains("TeamBuildTypes")) Then
Dim changeSetItemSpec As New ItemSpec(change.Item.ServerItem, RecursionType.Full)
labelItemsSpecs.Add(New LabelItemSpec(changeSetItemSpec, New ChangesetVersionSpec(changeSets(i)), False))
'Now actually label the items. Remove the exisitng label if any.
Dim PrevResults() As LabelResult = tfvc.DeleteLabel(LabelName, "$/" & project)
Dim results() As LabelResult = tfvc.CreateLabel(labelToCreate, labelItemsSpecs.ToArray(), LabelChildOption.Replace)
Now that we have the labelled version which we want to build, we will use the TFS Build APIs to actually execute the build and associate the changesets which we have gathered with that build.
public bool ModifyTfsBuildProj(string label, string SelectedBuild)
List<Changeset> changeSetList = new List<Changeset>();
foreach(int cs in changeSets)
//Get the build defiition object
IBuildDefinition buildDef = bs.GetBuildDefinition(project, SelectedBuildType);
//Create a build request object
IBuildRequest request = buildDef.CreateBuildRequest();
// Specify that we want to get labeled version
request.GetOption = GetOption.Custom;
request.CustomGetVersion = "LDemo";
//Put the build in queue
QueuedBuild = bs.QueueBuild(request);
// Get the details object of the queued build so that we can associate changesets to it.
IBuildDetail build = QueuedBuild.Build;
//Specify that we want to associate non-default changesets
catch (Exception ex)
Public Function ModifyTfsBuildProj(ByVal label As String, ByVal SelectedBuild As String) As Boolean
Dim changeSetList As New List(Of Changeset)()
For Each cs As Integer In changeSets
'Get the build defiition object
Dim buildDef As IBuildDefinition = bs.GetBuildDefinition(project, SelectedBuildType)
'Create a build request object
Dim request As IBuildRequest = buildDef.CreateBuildRequest()
' Specify that we want to get labeled version
request.GetOption = GetOption.Custom
request.CustomGetVersion = "LDemo"
'Put the build in queue
QueuedBuild = bs.QueueBuild(request)
' Get the details object of the queued build so that we can associate changesets to it.
Dim build As IBuildDetail = QueuedBuild.Build
'Specify that we want to associate non-default changesets
Catch ex As Exception
Only a small part of the code remains now that is to delete the label
public void DeleLabel()
tfvc.DeleteLabel("Demo", "$/" + project);
Public Sub DeleLabel()
tfvc.DeleteLabel("Demo", "$/" & project)
TfsBuild.Proj file of the build which needs to be executed should have an overriding target named CoreGetChangeSetsAndAssociateWorkItems. This target should be empty to override the default behaviour of Team Build. By default Team Build compares the labels of old build and new build of the same type and associates only the changesets which are not in the earlier label. It should appear as:
<Target Name="CoreGetChangesetsAndUpdateWorkItems" />
Summary: What this code has shown us is the functionality to handle various operations related to build and version control through code. We have seen how to find the build definitions, builds of specific definition, changesets which were considered for that build, latest changeset in the repository, label the files in a list of changesets, execute the build which does not get the latest version but a labelled version and finally associate certain changesets with the executing build.
The entire set of code is available for download from http://custombuildmanager.codeplex.com. It is just a boilerplate and beta code and author makes no explicit assertion about the completeness and accuracy of code but it should get you going on a path to create your own application.
Subodh Sohoni is a VSTS MVP, MCTS - Microsoft Team Foundation Server - Configuration and Development and also is a Microsoft Certified Trainer(MCT) since 2004. Subodh works as VP, Technology with SEED Infotech Ltd
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!