Creating a .NET Core Global Tool05 Oct 2020
I have now built my first .NET Core Global Tool!
A .NET Core Global Tool is special NuGet package that contains a console application that is installed globally on your machine.
It is installed in a default directory that is added to the PATH environment variable.
This means you can invoke the tool from any directory on the machine without specifying its location.
The Application 🌱
So, rather than the usual Hello World example to install as a global tool I wanted a tool that would be useful to me.
I wanted to build a tool that will create a folder prefixed with either a bespoke reference (in my case a Trello card number) or the current date in a YYYY-MM-DD format followed by a normal folder name.
The tool once it has created the folder will then also copy some dotfiles that I find useful in most projects over.
It will also copy the following dotfiles over:
I won’t explain how this code was written; you can view the source code over at GitHub to understand how this was done.
The important thing to note is that the application is a standard .NET Core console application that you can create as follows:
dotnet new console -n solrevdev.seedfolder
What sets a standard .NET Core console application and a global tool apart is some important metadata in the `.csproj` file.
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <PackAsTool>true</PackAsTool> <ToolCommandName>seedfolder</ToolCommandName> <PackageOutputPath>./nupkg</PackageOutputPath> <NoDefaultExcludes>true</NoDefaultExcludes> <Version>1.0.0</Version> <Title>solrevdev.seedfolder</Title> <Description>A nice description of your tool</Description> <PackageDescription>A nice description of your tool</PackageDescription> <Authors>your github username</Authors> <Company>your github username</Company> <RepositoryUrl>https://github.com/username/projectname</RepositoryUrl> <PackageProjectUrl>https://github.com/username/projectname</PackageProjectUrl> <PackageReleaseNotes>https://github.com/username/projectname</PackageReleaseNotes> <PackageLicenseExpression>MIT</PackageLicenseExpression> <RepositoryType>git</RepositoryType> <PackageTags>dotnetcore;;dotnet;csharp;dotnet-global-tool;dotnet-global-tools;</PackageTags> </PropertyGroup> </Project>
The extra tags from
Version are required fields while the
PackageTags are useful to help describe the package in NuGet and help get it discovered.
Packaging and Installation ⚙
Once I was happy that my console application was working the next step was to create a NuGet package by running the dotnet pack command:
This produces a nupkg package. This nupkg NuGet package is what the .NET Core CLI uses to install the global tool.
So, to package and install locally without publishing to NuGet which will be needed while you are still testing you need the following:
dotnet pack dotnet tool install --global --add-source ./nupkg solrevdev.seedfolder
Your tool should now be in your path accessible from any folder.
You call your tool whatever was in the ToolCommandName property in your .csproj file
You may find you need uninstall and install while you debug.
To uninstall you need to do as follows:
dotnet tool uninstall -g solrevdev.seedfolder
Once you are happy with your tool and you have installed in globally and tested it you can now publish this to NuGet.
Publish to NuGet 🚀
Head over to NuGet and create an API Key
Once you have this key go to your GitHub Project and under settings and secrets create a new secret named
NUGET_API_KEY with the value you just created over at NuGet.
Finally create a new workflow like the one below which will check out the code, build and package the .NET Core console application as a NuGet package then using the API key we just created we will automatically publish the tool to NuGet.
Each time you commit do not forget to bump the version tag e.g.
name: CI on: push: branches: - master - release/* pull_request: branches: - master - release/* jobs: build: runs-on: windows-latest steps: - name: checkout code uses: actions/checkout@v2 - name: setup .net core sdk uses: actions/setup-dotnet@v1 with: dotnet-version: '3.1.x' # SDK Version to use; x will use the latest version of the 3.1 channel - name: dotnet build run: dotnet build solrevdev.seedfolder.sln --configuration Release - name: dotnet pack run: dotnet pack solrevdev.seedfolder.sln -c Release --no-build --include-source --include-symbols - name: setup nuget if: github.event_name == 'push' && github.ref == 'refs/heads/master' uses: NuGetemail@example.com with: nuget-version: latest - name: Publish NuGet uses: firstname.lastname@example.org with: PROJECT_FILE_PATH: src/solrevdev.seedfolder.csproj # Relative to repository root NUGET_KEY: $ # nuget.org API key PACKAGE_NAME: solrevdev.seedfolder
Find More 🔍
Now that you have built and published a .NET Core Global Tool you may wish to find some others for inspiration.