Introducing dotGet: an installer for .NET Core CLI apps

Toni Solarin-Sodara
3 min readJan 16, 2018

--

It’s been about two years since .NET Core was publicly released and in that time, it’s undergone a lot of changes. From the re-introduction of csproj to the inception of the .NET Standard and a host of other things, it’s quite an eventful time to be a .NET developer.

Currently, .NET Core is used to build applications launched via the command line and at this time there’s no easy way to distribute and install these CLI apps and have the commands they export available from the system path, kinda like npm install -g.

dotGet was created to solve this problem. It makes it easy to install .NET Core command line apps, distributed via NuGet. This article will introduce you to the dotGet app and also walk you through making an app “dotGet ready”, using standard NuGet packaging techniques.

The App

For demonstration purposes we’re gonna build a very simple app that mimics the tree command available in most *nix based systems. Let’s call it branches, here’s the code:

The above code simply prints out a tree of subdirectories and files starting from the directory the app is run from.

Next, we’ll take a look at the csproj project file:

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>branches</AssemblyName>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
</Project>

You use the AssemblyName property to set the file name of the output binary as well as the command the user will run after installing your app. In this case the command to run will be branches. Every other content is up to you, but you do have to target a netcoreapp*.* framework. Once you’re done go ahead and publish your app; dotnet publish -c Release.

The NuGet Package

Now we’re done building our simple app, all that’s left is to generate and publish the NuGet package. Here’s the nuspec for Branches.Net:

You’ll see that on line 18 we copy the contents of the publish folder to a .NET Core app framework subdirectory in the tools folder, that’s really all we need to do in our NuGet package for dotGet to fully make use of it. You can go ahead to do whatever else you might want to in the nuspec, there’s nothing stopping your NuGet package from being used as a normal package reference and a dotGet compatible package. Once you’re ready, pack and publish your new package to the official NuGet gallery using your preferred method.

Installing with dotGet

Now that Branches.Net is published, the next step will be to install and use it. First, you have to install dotGet using the instructions here. Once dotGet is installed we simply need to run dotnet get install Branches.Net. We’ll see the following output:

Installing branches.net (1.0.0)
Registering command 'branches'
branches.net (1.0.0) installed successfully!

And there we have it! Now you can run the branches command and you’d get a print out of the tree of subdirectories and files starting from the directory it was run in (on Windows you might have to restart your shell instance to refresh the PATH variable). See the documentation to get more info on the dotGet commands including installing a specific package version, updating, uninstalling etc.

Some things to note

  • You can have multiple CLI apps in a single package, you just need to copy the publish files of each app to the same netcoreapp*.* sub folder of the NuGet package.
  • Currently, dotGet will select the latest version of netcoreapp*.* if more than one is present (e.g netcoreapp2.0 over netcoreapp1.1)
  • dotGet doesn’t, at this time, check if you have the required shared runtime version installed. When you invoke the command of the just installed package, dotnet will direct you to install the appropriate shared runtime version.
  • Only NuGet packages on the official gallery can be installed now. In the future dotGet will support custom NuGet feeds and possibly other forms of distribution (e.g. git repos)

Aaaaaaand that’s a wrap! I hope this article was informative enough and that dotGet is as useful as I intend it to be.

Cheers.

--

--

Toni Solarin-Sodara

Microsoft MVP | .NET Contributor | C# Enthusiast | Mildly Uninteresting