Last week’s post was an overview of the .NET CLI. This week I am going to cover creating a new custom tool for the CLI. This post is going to assume you already has the .NET CLI installed. If not check out last week’s post for instructions.
Getting Started
The tools used by the .NET CLI are just console applications so to begin create a new console application using the CLI with the following commands in a new directory.
dotnet new dotnet restore
Now that you have a new console application open the new folder up with Visual Studio Code (or the editor of your choice). The tool I am creating will count the files in a project. Very contrived I know, but I wanted to keep this simple and not get distracted by the details of what the tool actually does.
Project.json
The following is the project.json from my file counter tool. The big thing to note is “outputName”: “dotnet-fc” in the buildOptions section. In this example dotnet-fc will make the tool callable from the CLI using dotnet fc. The leading dotnet lets the CLI find the tool and the bit after the dash is the verb that is used with the CLI to execute the tool.
{ "version": "1.0.0-*", "description": "Test creation of a .NET CLI Tool", "buildOptions": { "emitEntryPoint": true, "outputName": "dotnet-fc" }, "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-3002702" } }, "frameworks": { "netcoreapp1.0": {} } }
Program.cs
The following is the actual code from the tool that counts the number of files. Again I don’t want this to be the focus of the post, but I am including it for completeness.
using System; using System.IO; using System.Linq; namespace ConsoleApplication { public class Program { public static void Main(string[] args) { var fileCount = Directory .EnumerateFiles(Directory.GetCurrentDirectory(), "*.*", SearchOption.AllDirectories).Count(); Console.WriteLine($"{Directory.GetCurrentDirectory()} continas {fileCount} files"); } } }
The console write line is using string interpolation if you have not see it before check out this page.
NuGet
Now that the application is complete use the .NET CLI to create a NuGet package out of it. This functionality is built in to the CLI via the pack command.
dotnet pack
Inside your project directory the NuGet package can be found in the bin directory under either Debug or Release depending on what type of build was done. In my case the project is FileCounter so pack produced FileCounter.1.0.0.nupkg in the bin\Debug directory.
The next step is to add a new package source to your NuGet.Config file which can be found (on Windows) in the C:\Users\YourUser\AppData\Roaming\NuGet directory. In the packageSources section add a new key and value for the directory you want to use for the source of the new tool. The following is my complete NuGet.Config with a new source for “local”.
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> <add key="local" value="C:\NuGetLocal" /> </packageSources> </configuration>
Using the New Tool
Open the project that you want to use the new tool with using Visual Studio Code (or any text editor). The new tool will need to be added to the tools section of the project.json file. The following is an example of a full project.json as it exits from using dotnet new with an added tools section.
{ "version": "1.0.0-*", "buildOptions": { "emitEntryPoint": true }, "dependencies": { "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.0-rc2-3002702" } }, "tools": { "FileCounter": { "version": "1.0.0" } }, "frameworks": { "netcoreapp1.0": { "imports": "dnxcore50" } } }
Now from the CLI do a dotnet restore and the new tool should be ready to use. In the case of this example you can now run dotnet fc and get a count of the files in your project’s directory.
Lessons Learned
This was the first time I had worked with local NuGet packages and I spent a good bit of time learning where to find the NuGet.Config and the local NuGet caches (C:\Users\YourUser\.nuget\packages and C:\Users\YourUser\.nuget\packages\.tools) were located and the proper edits to make.
The other big thing I would do different the next time around would to be to take advantage of the fact that the .NET CLI will find tools that are on the system path. During development it would have been much simpler than having to go clear the local NuGet caches or change the version number of the tool.
Update
Code used in this post can be found in this GitHub repo.
Great info – any chance you have some working code to share on GitHub?
Thanks Ryan! I don’t currently. I will work on getting an example up on GitHub, but it maybe the weekend before I get it done. I will let you know when it is up.
Ryan I uploaded the code and it can be found here. Let me know if you have any issues!