This tutorial will explain how you can build your own buildsteps. In the old XAML-builds you had a workflow that was very hard to customize. In TFS 2015 we have a new build-engine that works with a dynamic flow. You can select the steps that are needed to complete your build. In most of the builds these steps are something like:

  • Versioning
  • Compile with Visual Studio
  • Run tests with Visual Studio
  • Publish build-drop

For the most common things needed in a build, you can use the out of the box buildsteps created and maintained by the community and Microsoft. In some cases, you need to create your own buildstep. In this post I will explain how to create your own custom buildstep.


Before we begin, you need tools to create, upload and edit the buildsteps. I use the following tools:

Create buildsteps

Creating a task is a very easy. After you have installed tfx, you can use the following command to create a task:

tfx build tasks create --task-name MyNewTask --friendly-name "My New Task" --Description "This is my first new task" --Author "Jeroen"

The output of that command should be something like:

An important thing to note is the ID of the task. You will need this ID to download and upload existing tasks to TFS. Also note that there are some files created by tfx on your local PC. (in my case in P:\MyNewTask).

The following files have been created:

  • icon.png – this is the icon your task will get in the task library. You can replace this one with your own icon. The size of the icon should be 32x32 pixels.
  • sample.js – This file contains the logic when you want to run your task on a non-windows environment. I won’t use this file in this tutorial, our task will only work on Windows machines.
  • sample.ps1 – This file contains the logic when you want to run your task on a Windows machine. The logic is scripted in Powershell. (You better love Powershell, it will be the future J)
  • task.json – This file contains metadata of your task. Properties of you task, the form you see in the build editor and some executionproperties are defined in this file.

At the time when I write this tutorial, Microsoft Release Manager is still not integrated in TFS 2015. Since my organization is using Release Manager a lot, I will create a task that will start a new release in Release Manager.

Edit Task.json

I have edited the task.json file to the following:

  "id": "18991330-cab3-11e5-ba90-df22c8efcea9",
  "name": "ReleaseManager",
  "friendlyName": "Release Manager Release",
  "description": "Trigger a release via Release Manager",
  "author": "J. Niesen",
  "helpMarkDown": "This task will trigger a release in Release Manager",
  "category": "Deploy",
  "visibility": [
  "demands": [],
  "version": {
    "Major": "0",
    "Minor": "1",
    "Patch": "15"
  "minimumAgentVersion": "1.83.0",
  "instanceNameFormat": "Trigger release",
  "inputs": [
      "name": "ReleaseTargetStage",
      "type": "string",
      "label": "Release Target Stage",
      "defaultValue": "",
      "required": false,
      "helpMarkDown": "The last stage of the release"
  "execution": {
    "PowerShell": {
      "target": "$(currentDirectory)\\releasemanager.ps1",
      "argumentFormat": "",
      "workingDirectory": "$(currentDirectory)"

Important variables in the task.json file:

  • Id – The ID of your task, never change this property
  • Name – The Internal name of your task
  • FriendlyName – The display name of your task
  • Description – The description of your task
  • Author – The author of your task
  • HelpMarkDown – The help text that is showed for this task
  • Category – The category in which your task will be available
  • Version – The version of your task. Use semantic versioning for this!
  • MinimumAgentVersion – The minimum version of the agent that is needed to run this task.
  • InstanceNameFormat – The small text that is showed after you have added the buildstep to your builddefinition.
  • Inputs – The inputs of your task
  • Execution – The logic files (like sample.js and sample.ps1) that are executed when your task is executed.

As you may have noticed, I changed the name of sample.ps1 to releasemanager.ps1 and removed the sample.js from the execution. I also had to raise the version a couple of times since I had to test the task. Every time when you update your task, you have to raise the version number. If you don’t do this, the task will not be updated on your build agents.

Please check the manifest reference of Microsoft for a full reference of the task.json file.

Edit sample.ps1

First of all, I changed the filename of sample.ps1 to releasemanager.ps1. I don’t like names as sample.ps1, they don’t describe the content.

I changed the content of the file to the following:

param (

### Init variables ###
$Collection = $env:system_TeamFoundationCollectionUri
$BuildDefinition = $env:build_DefinitionName
$PathRmClient = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Release Management\Client\bin\ReleaseManagementBuild.exe"
$TeamProject = $env:System_TeamProject
$BuildNumber = $env:Build_BuildNumber

Write-Host "Path RM Client: $PathRmClient"
Write-Host "Collection: $Collection"
Write-Host "TeamProject: $TeamProject"
Write-Host "BuildDefinition: $BuildDefinition"
Write-Host "ReleaseTargetStage: $ReleaseTargetStage"

# Import the Task.Common dll that has all the cmdlets we need for Build
import-module "Microsoft.TeamFoundation.DistributedTask.Task.Common"

### Trigger a release ###
$arguments = " -tfs `"$collection`" -tp `"$TeamProject`" -bd `"$BuildDefinition`" -bn `"$BuildNumber`" -ff $true"

if(![String]::IsNullOrWhiteSpace($ReleaseTargetStage)) {
    $arguments = $arguments + " -ts `"$ReleaseTargetStage`""

Write-Host "Starting: $PathRmClient"
Write-Host "Arguments: $arguments"

$process =Start-Process -FilePath $PathRmClient -ArgumentList $arguments -Wait -PassThru

Write-Host $process.StandardOutput
Write-Host $process.StandardError

Write-Host "Process Complete: $PathRmClient"

The file starts with a param statement. The parameters you define here, should be commonly named like the inputs you defined in your task.js file. After that, I initialize some variables. A list of variables is defined on Microsoft Developer Network. After I initialize some variables, the logic of this task will start.

Please note that this is not a complex task. In a more complexe task, you may need the logging commands.

Upload buildsteps

Now your task is ready, you need to upload it to TFS. You can upload your task to TFS by using the folling command in tfx:

tfx build tasks upload –task.path {path to your task}

You should now be able to add the buildstep to your builddefinition:

Also have a look at the properties of the buildsteps we just added:


Share This