Click here to Skip to main content
15,900,108 members
Articles / .NET

Adding a Tool to a .NET Core Build

Rate me:
Please Sign up or sign in to vote.
4.87/5 (5 votes)
28 Apr 2017CPOL3 min read 11.4K   2   3
How to add a tool to a .NET Core build

I need a command line tool to run over some files in a project and generate some code that can then be built with the rest of the project's source code. However, the documentation to get this to be an automatic step of the build is a bit lacking – there are plenty of articles on creating a .NET Core CLI tool, however, these have to be manually invoked at the command prompt.

Background

.NET Core project files (the Visual Studio 2017 csproj type) allow the NuGet packages to be specified in the same file as any other project/assembly reference. It also allows a special type of NuGet package that was created as a DotNetCliTool type to be pulled into a project and integrated with the rest of the dotnet tooling, for example:

dotnet restore
dotnet my-tool

The tool is just a standard .NET Core console application that runs in the projects directory and can receive command line arguments as any other console program can (i.e., dotnet my-tool argument would pass "argument" to the entry point of the program).

Creating a Tool

Creating a tool is simple: create a new .NET Core console app (MUST be a .NET Core App 1.0, not 1.1) and edit the project file to set the package type to be a .NET CLI tool (at the moment, there's no UI for this in Visual Studio, so you'll have to edit the csproj file, but that can be done from Visual Studio now by right clicking on the project and then there will be an Edit option in the context menu).

Here's an example project file:

XML
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.0</TargetFramework>
    <PackageType>DotNetCliTool</PackageType>
  </PropertyGroup>
</Project>

Another thing that we need to do is ensure the application is prefixed with dotnet- in order for it to work with dotnet. This can be done via the UI (the Assembly name in the properties) or by editing the csproj:

XML
<PropertyGroup>
  ...
  <AssemblyName>dotnet-example-tool</AssemblyName>
</PropertyGroup>

You can now build that and then create a NuGet package by running the dotnet pack command in the project's folder.

Using the Tool

For testing purposes, it's probably easier to put the tool on your local machine and set up Visual Studio to use the local package source:

NuGet Source

In another project, you can now reference the tool as a NuGet package. Unfortunately, at the time of writing the Visual Studio NuGet UI throws an error of "Package ExampleTool" has a package type "DotNetCliTool" that is not supported by project "ExampleConsole". This means you'll need to edit the csproj file to include it manually:

XML
<ItemGroup>
  <DotNetCliToolReference Include="ExampleTool" Version="1.0.0" />
</ItemGroup>

To test if this works, open the command prompt in the project's directory and run the following:

dotnet restore
dotnet example-tool

You should see "Hello World!" displayed (or whatever you made your program do). We're nearly there, however, I wanted to the tool to run before each build so it can generate some source files that get swept up in the build – at the moment, it's a manual step.

Integration with the Build

Although the project.json was nice and compact, one advantage of moving back to MSBuild is we can now take advantage of the exec task to run our tool during the build. To do this, edit the csproj file of the project consuming the tool to add the following:

XML
<Target Name="RunExampleTool" BeforeTargets="Build">
  <Exec Command="dotnet example-tool" WorkingDirectory="$(ProjectDir)" />
</Target>

Now when you build the solution, if you check the build output, you should see "Hello World!" in there. Success!

Analysing the above, you can see that we've created a target that runs before the built in Build task (note you used to be able to just name your task BeforeBuild, however, this no longer works – I'm guessing it's a result of no longer including the common targets?). Next the task the target will run is an exec task, which invokes our tool (via the dotnet command). Here the important thing to note is that we're setting the working directory to be the project's directory, which is achieved using the MSBuild macro $(ProjectDir) – dotnet will only automatically pick up the tool from the NuGet packages if we're in that directory.

That's it, quite simple but took me a while to piece everything together as the documentation is missing in some areas and I guess it's not a common thing I'm trying to achieve.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionThanks but I have a question Pin
Hamed Fathi29-Apr-17 3:08
Hamed Fathi29-Apr-17 3:08 
AnswerRe: Thanks but I have a question Pin
Samuel Cragg29-Apr-17 20:58
Samuel Cragg29-Apr-17 20:58 
PraiseRe: Thanks but I have a question Pin
Hamed Fathi30-Apr-17 0:17
Hamed Fathi30-Apr-17 0:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.