Exploring global .NET Core tools
.NET Core allows us to create and run .NET apps on many platforms, but actually shipping our apps is hard, especially if those apps aren’t web apps that use one of the well-integrated publishing methods (WebDeploy, Azure, Docker, …).
Node already allows to package up apps and then install and use them using:
> npm install -g something
> something
The upcoming .NET Core SDK 2.1.300, slated to be released with .NET Core 2.1, will offer a similar functionality:
> dotnet tool install -g something
> something
These applications are downloaded and installed from NuGet and are marked as a special package type.
So let’s build one ourself. Get a preview 2.1.300
.NET Core SDK version from the links at https://github.com/dotnet/cli to follow along. The full sample is available on GitHub at https://github.com/dasMulli/GlobalCliToolsExample.
Some config first
In order to use preview packages from the nightly feed and use our built nuget packages:
- Create a folder to work in, this will be the base for all commands run
- Create a folder named
nupkgs
that will hold our built NuGet packages - Run
dotnet new nugetconfig
to generate anuget.config
file. Edit it to add the custom folder and the CI feed:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="local-packages" value="./nupkgs" />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
</packageSources>
</configuration>
Create the app
So we now need an application to work with. As a good sample, let’s create a program that just greets the user:
> dotnet new console -o sayhi.tool
This will create a folder sayhi.tool
and a console app and .csproj
file inside of it. First, I don’t like “Hello World!” that much, so changed the Program.cs
file to something slightly more interesting:
static void Main(string[] args)
{
Console.WriteLine($"Hi {Environment.UserName}!");
}
Mark the app as tool
In order to be packed correctly so that we can install the app as a tool, we need to change the sayhi.tool.csproj
file a little:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PackAsTool>true</PackAsTool>
<ToolCommandName>sayhi</ToolCommandName>
<PackageOutputPath>../nupkgs</PackageOutputPath>
</PropertyGroup>
</Project>
Using netcoreapp2.1
will cause the tool to break between .NET Core 2.1 preview/RC/RTM releaes. You will need to release/publish a new version of your global tool once the framework you target becomes RTM / "stable".
While you may recognize OutputType
and TargetFramework
from normal csproj files, there are a few new ones here:
PackageOutputPath
: This tellsdotnet pack
where to put the.nupkg
file to. This propertiy isn’t new and alredy exists in released tooling. For our example, it needs to point to the path we configured innuget.config
.PackAsTool
: This instructs the tooling to package our app correctly for being installed as a tool.ToolCommandName
: This lets us choose the command line executable name for the app. It defaults to the assembly name of the application, but want to typesayhi
instead ofsayhi.tool
in this example.
Build and run!
In the top level folder for this sample, run:
> dotnet pack -c Release
…
Successfully created package 'C:\repos\GlobalCliToolsExample\nupkgs\sayhi.tool.1.0.0.nupkg'.
> dotnet tool install -g sayhi.tool
The installation succeeded. If there are no further instructions, you can type the following command in shell directly to invoke: sayhi
You may see some warnings because of prerelease version numbers being used by the preview tooling - you can ignore them.
Now to be safe, open up a new console window. You can skip this if you already used global tools before, but if this is your first dotnet install
call, you may still need to do so.
Our program can now be run from the command line using just:
> sayhi
Hi martin.ullrich!
Where is it installed to?
Our sayhi
tool is installed into a .dotnet\tools
folder in the user’s directory:
The install command generates a .exe
file as a warpper on windows and shell scripts on macOS / Linux. On windows, this is currently a .NET Framework executable, but it is planned to be replaced with a native executable for an upcoming preview.
Bonus: Integrate with the dotnet
command
The dotnet
CLI always allowed to use programs named dotnet-something
as verbs (=> dotnet something
). This is now possible with global tools as well.
To do so, let’s create a similar application greet.tool
using the same steps as above, but in greet.tool.csproj
, set ToolCommandName
differently:
<PropertyGroup>
<ToolCommandName>dotnet-greet</ToolCommandName>
</PropertyGroup>
Now build and install this tool:
> dotnet pack
> dotnet tool install -g greet.tool
And it can be run using:
> dotnet greet
Hi martin.ullrich!
Sample code
The full sample is avilable at https://github.com/dasMulli/GlobalCliToolsExample.
Use appsettings.json and environment overrides in classic ASP.NET apps
Supercharge your classic ASP.NET apps with the config system introduced in ASP.NET Core Continue reading