How to Create Azure DevOps Custom Build Tasks

The build pipeline can be greatly enhanced and customized to your organization's needs. Your custom tasks can be as simple as a few lines of Powershell script, or more complicated by creating your own command line utility.

The aim of creating custom build tasks is modularity and re-usability. Breaking up your pipeline like this makes things less fragile, too - perhaps compared to one large mega script.

Step 1 - Create folder structure

This demo will show you how to create a custom build task, which uses a Powershell script to call a custom command line utility. The CLI utility gives us great flexibility, but if you can achieve what you need purely with Powershell, then it isn't necessary.

Create the following folder structure:

Custom task folder structure

Step 2 - Task Definition

First task is to create the package definition metadata file task.json, which goes in the Task folder. A good place to start is our full downloadable example. For more info about task.json, check out the task.json schema on Microsoft's GitHub.

Example task.json file

  • Id - Add a unique GUID using guidgenerator.com
  • Give the task a name, friendly name, description and author
  • Category decides which tab it appears on when you add the task to a build. Can be 'Build', 'Utility', 'Test', 'Package', 'Deploy' or 'Tool'
  • Version Builds will always use the latest version of your task within the same major version. So if your build uses v1.0.0 and you create a v1.1.0, the build agents will automatically start using v1.1.0. They will not use v2.0.0 unless you explicitly go into the build and change the version from the drop down.
  • MinimumAgentVersion ensures build agents using your task are compatible. If you are using on-premise TFS then just set this to be the same version as your build agents.
  • InstanceNameFormat will be used as the task title whenever you add it to a build
  • Inputs - The is where you can define various variables to pass to your script. You can use string, boolean, multiline, filePath, pickList or radio (others are available but these are the most common ones).
  • Execution - this section tells what script to run when the task is executed. You can use $(currentDirectory) to execute a script in the task's root folder.

You can also add a 32 x 32 png icon in the root of your task folder, which should be named icon.png.

Step 3 - Powershell Script

To get the parameters set by the user (as defined in the 'inputs' section is Task.json above), add this snippet to the top of your powershell script. This script also goes in the Task folder, with the same filename set in the 'Execution' property of your task.json file.


        param(
            [string] $someString,
            [string] $anotherString
        )

Here is a complete example of a Powershell script that calls the custom CLI tool we are going to write, with the 'someString' and 'anotherString' values:

Example Powershell file

Step 4 - Custom CLI Tool

We are going to create a custom command line tool, which is called by the Powershell script above. The Visual Studio solution file goes in the Command folder, with the rest of the source code and .csproj file in the MyCustomTaskCLI folder underneath.

The first step is to create a .Net console app. You can read the arguments passed in from the Powershell script by parsing the 'args' collection passed into the Main() method. This code snippet will tell you what has been passed in:


        static void Main(string[] args)
        {
            foreach(var arg in args)
            {
                Console.WriteLine(arg);
            }
        }

Anything you write to the Console window will end up in the TFS build logs. To ensure TFS can identify if the tool exited correctly, or encountered an error, you need to exit the program with the correct code. This is just a matter of calling Environment.Exit with zero or one, for success or failure respectively.

When you have finished writing your custom CLI tool, build it in Release mode, and copy the contents of the /bin/Release folder to MyCustomTask -> Task -> MyCustomTask folder. This will make sure it gets zipped up along with your task.json and other task artifacts before uploading it to your TFS or DevOps server.

Step 5 - Upload to TFS/Azure DevOps

Lots of blogs recommend using TFX to upload your task, however I find it much easier to simply use this UploadBuildTask.ps1 script to upload it directly using the TFS API. The path is that of your task.json file.


        .\UploadBuildTask.ps1 "C:\Temp\MyCustomTask\Task" http://your-tfs-server:port/tfs/default

Your new custom build task should now be available to add to your build pipelines. If you need to update the task, don't forget to tick up the version number in task.json. You can download the full example here.

If you or your organization requires assistance with your devops function, including build and deploy with on-premise TFS or Azure DevOps, don't hesitate to contact us.