TFS2010 – Queuing a Build (from code) With Custom Process Parameter Values

I got a question today on how to access the process parameters of a build definition in 2010. If you haven’t looked at that property, yet, you might be surprised to find out it is just a string. Unfortunately, we chose to do it this way for various reasons. It would more naturally be a dictionary of name value pairs. Well, in fact, it is just that. We simply took the dictionary and serialized it into a string.

So, the question becomes… How do I deserialize this thing change it and serialize it back into a definition, build request, or other objects that it hangs off of?

The easiest thing to do is simply show you the code. In this example, I am queuing a build from code and setting the Verbosity process parameter to Diagnostic. Here’s the code:

using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Workflow;
using Microsoft.TeamFoundation.Client;

namespace ManageBuildTemplates
class Program
static void Main(string[] args)
TfsTeamProjectCollection collection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(“http://jpricket-test:8080/tfs/collection0”));
IBuildServer buildServer = collection.GetService<IBuildServer>();

IBuildDefinition definition = buildServer.GetBuildDefinition(“UnitTests”, “Definition1”);

IBuildRequest request = definition.CreateBuildRequest();
request.ProcessParameters = UpdateVerbosity(request.ProcessParameters, BuildVerbosity.Diagnostic);


private static string UpdateVerbosity(string processParameters, BuildVerbosity buildVerbosity)
IDictionary<String, Object> paramValues = WorkflowHelpers.DeserializeProcessParameters(processParameters);
paramValues[ProcessParameterMetadata.StandardParameterNames.Verbosity] = buildVerbosity;
return WorkflowHelpers.SerializeProcessParameters(paramValues);

In the example you can see that the UpdateVerbosity method does the deserialization and serialization using the WorkflowHelpers class. These are public methods and they are the same ones we use internally.

Note that if you want to add custom types as process parameters, they MUST be serializable using the XAML serialization engine.

Code away!


I should have mentioned this the first time, but here is some additional information you may want to know about process parameters. Values for process parameters exist in several places: in the XAML template as default values, on the definition, as part of the build request (seen here), and eventually on the build detail. So, which values matter? When the build machine loads the process template (XAML) it first overrides any process parameter values with the values from the definition. Therefore, if you assign a value to a process parameter on the definition (this will bold the value in the property grid of the definition), the definition value will be used. The build machine then overrides the process parameter values with the value from the build request. So, if you specified a value in the XAML, in the definition, and in the build request, ONLY the value in the build request will be used.

And now to answer the original question: Why are the build request process paramters empty? Shouldn’t they be a copy of the definition? To save on space (and for other reasons), only the values overriden at each level are saved at that level. We don’t copy the values from the XAML to the definition, or from the definition to the process parameters. So, if you wanted to change the value of a process parameter based on the value already stored on the definition in the above example, you would deserialize the definition’s process parameters instead of the build request’s.

Comments (6)

  1. devin2l says:

    This is great!  Thanks for answering.  The only thing was we received an empty request.ProcessParameters and instead had to use definition.ProcessParameters.  Not sure why the discrepancy, but it worked.



  2. Good point! I have added an explanation to the post.



  3. Travis says:


    Thank you for the great post. I have a question regarding what an 'XML formatted string' looks like. I have a web based build tool that allows users to append whatever MSBuild parameters they want, through a simple text box. This worked fine in 2008, but is no longer working in 2010. I assume that this is because IBuildRequest.ProcessParameters now represents an XML formatted string.

    Example: A user would select a build they want to execute, and could type '/p:publishBuild=true'. This would then be passed in as a parameter to MSBuild.

    I have tried basic strings like '<publishBuild>true</PublishBuild>' and 'publishBuild=true', unfortunately both throw a error.

    I am sorry if this is a very basic question, but I can not find an example of the types of strings that are being passed into your UpdateVerbosity method.

    Thank you for your help.


  4. Chetan says:

    Process parameters is empty while accessing from code, while in template these custom process parameters are assigned default values. Any idea?

  5. Christopher Painter says:

    Using TFS Service (not on-prem) I have a build definition that runs an msbuild script that calls TFSBuid.exe to queue up a number of builds. It works file but I can't pass process parameters.  I decided to take your advice and create my own custom TFSBuild.exe that could but I get the error:

    Unhandled Exception: Microsoft.TeamFoundation.TeamFoundationAuthenticationRedirectionException: TF30064: You are not authorized to access the server.

    I'm going to start working this but wondered if anyone else has already seen this?  I'm guessing it's trying to connect using the build service account credentias instead of the federated Microsoft Live account credentials.

  6. Anthony Tran says:

    Great Posts.

    I am using QUEUE Build VS 2013. I would like to modify the Build Process template (tfvc Template12.xaml) so that I can control the build version numbers, when I can

    Here is what I have added onto my TFS Build Process Template:

    <x:Property Name="IsMajorVersion"     Type="InArgument(x:Boolean)" />

       <x:Property Name="IsMinorVersion"     Type="InArgument(x:Boolean)" />

       <x:Property Name="IsBuildVersion"     Type="InArgument(x:Boolean)" />

       <x:Property Name="IsRevisionVersion"  Type="InArgument(x:Boolean)" />

    <mtbw:ProcessParameterMetadata ParameterName="IsMajorVersion"     BrowsableWhen="Always" Category="HCSCM"     DisplayName="2. Increment major number"    Description="Set to true to increment the major version number. Setting this property to true will reset the minor, build and revision numbers to zero." />

         <mtbw:ProcessParameterMetadata ParameterName="IsMinorVersion"     BrowsableWhen="Always" Category="HCSCM"     DisplayName="3. Increment minor number"    Description="Set to true to increment the minor version number. Setting this property to true will reset the build and revision numbers to zero." />

         <mtbw:ProcessParameterMetadata ParameterName="IsBuildVersion"     BrowsableWhen="Always" Category="HCSCM"     DisplayName="4. Increment build number"    Description="Set to true to increment the build version number. Setting this property to true will reset the revision number to zero." />

         <mtbw:ProcessParameterMetadata ParameterName="IsRevisionVersion"  BrowsableWhen="Always" Category="HCSCM"     DisplayName="5. Increment revision number" Description="Set to true to increment the revision version number." />

    The question is, how am I be able to control each build version numbers individually?

    For example:

    If I want just to increase the minor version number ( by +1)  only, by set it to TRUE.

    How do I make it works ?

    Thank you