Date posted: 25 Sep 2019, 1 minutes to read

Installing .NET Core tools: Preventing errors in your Azure Pipelines

I ran into a weird thing in .NET Core Global tools: If you try to install the tools while they are already installed on that system, .NET Core will throw an error and exit with a non-zero exit code.

This is not helpful in a Continuous Integration (CI) scenario!

Expected installation

Normally you expect that you run an install command like this:

dotnet tool install dotnet-stryker -g

And the tool would install. This is correct if you run it once.

In Azure DevOps you would call the command from a .NET Core task, as I previously described here.

Install command in Azure Pipelines

If you run the pipeline again, or the command locally, you get an error indicating that the tool is already installed!

This behavior seems rather odd to me: if the tool is already installed, then great. Perform a no-op (no operation) and go ahead with the next command.

In this issue on GitHub this behavior is described. The team has made a choice about doing it this way, even though they are not sure that this was the right choice. The current debate seems to be if the decision can be reverted (that would mean a breaking change from the old behavior) or adding a new parameter that would enforce the expected behavior.


The work around for this issue is almost as weird as the issue it self. You run the update command for the tool:

dotnet tool update dotnet-stryker -g


  • if the tool is not installed, it will install the latest version!

Seems strange behavior to me, but ok… At least it will return an exit code of 0 and we can move along.

If you run the command again, the tool will try to upgrade to the latest version, which is what I would expect. The logs do seem to indicate an interesting story… It seems to reinstall that same version (given there is no newer version available)…!

Result of dotnet update

Strange way of implementing this functionality, at least there is a work around to prevent the CI build from failing.

Update for multiple parallel executions

I needed to run a dotnet tool parallel on multiple machines in the same pipeline and then this method does not work. Seemed like a conflict when running the update command during the same time window.

To circumvent this, I had to create a small PowerShell script to check the output of the dotnet tool list -g command and first manually check if the tool was installed. You can find the code for it in this Gist.

Note: Not sure why the last exitcode is not 0 when running the regular .NET Core command in an Azure DevOps pipeline, so I had to enforce a normal exit code.