2

I'm developing an open-source library which mainly consists of one class-library project targeting .NET Standard 2.0. On top of that, I've also implemented a console app which is the CLI to this library. The console project (for historic reasons) only targets .NET Framework 4.6.2.

Now I wonder what would be the best practice in order to make this console app available to the community. On the broadest level, I see two possibilities:

  1. Ship the console app as a separate NuGet.
  2. Ship the console app in the same NuGet as the class library because it's just a minor add-on and does not justify an own package.

Historically, I've been using the second approach but considering that the class library can be used in a multi-targeting scenario, I'm not sure anymore. Maybe it's cleaner to separate the console app in a NuGet of its own so that it's dependency on the full .NET framework is clear.

Either way I wonder where the console exe belongs to in the file structure of the NuGet. Historically, I've been putting it under tools\net462 but a comment about the tools folder on this page made me insecure:

Powershell scripts and programs accessible from the Package Manager Console

I'm not necessarily imagining someone using the CLI from the Package Manager Consoler. Rather it would be used as stand-alone exe somewhere is some shell.

Dejan
  • 9,150
  • 8
  • 69
  • 117

3 Answers3

6

Ther is a solution that seems to fit your needs. You can create a command line extension for the dotnet tools. Like dotnet ef you can create a dotnet myAwesomeTool command. The only thing that you need to do is the Following:

Create a console application and add the following code to your .csproj

<PackageId>Company.MyAwesomeTool</PackageId>
<AssemblyName>dotnet-myAwesomeTool</AssemblyName>
<PackageType>DotnetCliTool</PackageType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>

Build the solution and you will find a nuget package in your bin folder. This nuget package can be distributed and when you have installed it, you can run dotnet myAwesomeTool in the projects where the nuget is installed. Works like a charm for me =)

To install it on other projects, add this to the csproj:

<ItemGroup>
  <PackageReference Include="company.MyAwesomeTool" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
  <DotNetCliToolReference Include="company.MyAwesomeTool" Version="1.0.0" />
</ItemGroup>

For more infos: https://blog.maartenballiauw.be/post/2017/04/10/extending-dotnet-cli-with-custom-tools.html

modmoto
  • 2,901
  • 7
  • 29
  • 54
  • This seems to fall down if the tool you built requires other (not-tool) nuget packages. (Error NU1212 on install) – Andy Joiner Jun 17 '19 at 16:07
  • I referenced a lot of "not tool" nuget packages to build the nuget tool and I did not get such an error. This was over a year ago, but I am pretty confident that it did not change until today. How would you build a nuget package without any other nuget package, lets say newtonsoft-json. I do not think this is the problem. – modmoto Jun 17 '19 at 16:56
2

In general, NuGet is meant only for delivering class libraries (note the wording "if your library...").

Use Chocolatey instead for deploying command-line and GUI apps to Windows. It has a CLI that can be used to easily install and update applications. It is not NuGet, but uses a similar method to package and deploy the app.

There are also package managers to target other platforms:

  1. apt-get (for Debian/Ubuntu/Mint)
  2. Brew (for MacOS)
  3. RPM (for Fedora/Red Hat)

NOTE: As Martin Ullrich pointed out in the comments, there is now a way to deploy build tool CLIs with NuGet, which is primarily meant for continuous integration deployment scenarios.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • 1
    Interesting. However, visiting this page, the first thing I read is: "Chocolatey - The package manager for Windows". That excludes Linux/Mac, I guess? Which is the foremost reason I targeted .NET Standard. – Dejan Jan 04 '18 at 17:46
  • 2
    @Dejan You should use whatever package managers exist for those platforms....apt-get, brew, rpm or whatever. NuGet should only be used to serve up class libraries. – mason Jan 04 '18 at 17:48
  • @mason: that's an interesting comment: "NuGet should only be used to serve up class libraries." If this is true, then that answers my question. Can you back up this claim a little bit and post it as an answer? – Dejan Jan 04 '18 at 17:50
  • @Dejan - Well, that only becomes a concern if you target .NET Core with your CLI app. But as mason mentioned, there are other package managers that can be used for other platforms. – NightOwl888 Jan 04 '18 at 17:50
  • 3
    @Dejan I don't have any firm statements from a well respected authority. People have varying opinions. For example [this Microsoft employee](http://mitchdenny.com/the-tyranny-of-nuget/) doesn't like using NuGet packages (.nupkg) for anything except class libraries. I have no object to the use of the .nupkg in Chocolatey or [Octopus](https://octopus.com/) or [PowerShellGet](https://github.com/PowerShell/PowerShellGet). My concern is with polluting the NuGet repository (nuget.org) with packages that don't contain class libraries. The repository should have a single purpose. – mason Jan 04 '18 at 18:13
  • @mason: I'm very glad you clarified this to me. I absolutely agree. – Dejan Jan 04 '18 at 18:15
  • @Dejan If you're distributing to Windows, note also that [UWP](https://en.wikipedia.org/wiki/Universal_Windows_Platform_apps#APPX) is appropriate. Things seem to be moving (slowly) in that direction. UWP is built into Windows 10, supports console apps, and is easily distributed via download (just a .appx file) or the Windows Store. And it's the only way to get 3rd party programs onto (still rare) Windows 10 S. – mason Jan 04 '18 at 18:33
  • 1
    If it is a true "tool" NuGet you can create a CLI tool package that can be added on a per-project basis. the upcoming 2.2.0 version of the CLI will also have "global" tools via `dotnet install tool`. Doc for per-project tools: https://learn.microsoft.com/en-us/dotnet/core/tools/extensibility#per-project-based-extensibility – Martin Ullrich Jan 05 '18 at 19:23
1

When time pass by, other solutions come available...

https://learn.microsoft.com/nl-nl/dotnet/core/tools/global-tools-how-to-create

<PackAsTool>true</PackAsTool>
<ToolCommandName>botsay</ToolCommandName>
<PackageOutputPath>./nupkg</PackageOutputPath>
Stijn Van Antwerpen
  • 1,840
  • 17
  • 42