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("https://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);

            buildServer.QueueBuild(request);
        }

        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!

UPDATE:

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

  • Anonymous
    March 26, 2010
    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. Thanks! Kevin

  • Anonymous
    April 04, 2010
    Good point! I have added an explanation to the post. Thanks, Jason

  • Anonymous
    January 17, 2011
    The comment has been removed

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

  • Anonymous
    January 18, 2013
    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.

  • Anonymous
    January 07, 2016
    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