Build a Linux CLI app with .NET Core

animesh

Animesh Bulusu

Posted on May 14, 2019

Build a Linux CLI app with .NET Core

Being a developer and a geek for as long as I can remember, command line tools have always fascinated me. They are relatively easy to create and use than a web app or a desktop app.

In this post, we will explore how to build a simple command line tool on Linux using .NET Core.

Create a new console app using the dotnet cli.

$ dotnet new console -o netcore-test-cli
$ code netcore-test-cli
Enter fullscreen mode Exit fullscreen mode

Most command line tools do take user input and perform actions as based on these inputs.

These inputs come into the Main function during runtime by the way of the string[] args parameter. We could simply parse the arguments and their values from the string array args, but this is a tedious thing for us to do.

Fortunately, there are many open source libraries to help us do this. One such library is CommandLineParser. I have used it in a couple of projects and like it.

Let us add this command line parsing library to the project.

$ dotnet add package CommandLineParser
Enter fullscreen mode Exit fullscreen mode

To get started with CommandLineParser, first we need to specify the types and names of the arguments in the form of an Options class. Then we need to use a Parser instance to parse the arguments provided.

var result = Parser.Default.ParseArguments<Options>(args)
Enter fullscreen mode Exit fullscreen mode

On successful parsing, we get back a Parsed<Options> type. Otherwise, we get back a NotParsed<T> type which is an error collection of type IEnumerable<Error>.

The prescribed way to do this is to use the WithParsed and WithNotParsed extension methods which take on the respective parsed types and pass the parsed options to further processing.

static void Main(string[] args)
{
    Parser.Default.ParseArguments<Options>(args)
        .WithParsed<Options>(options => ProcessOptions(options))
        .WithNotParsed<Options>(options => HandleErrors(options));
}
Enter fullscreen mode Exit fullscreen mode

For the sake of simplicity, let us define two options, Count and Name, as follows.

class Options
{
    [Option('c', "count", HelpText="The count variable")]
    public int Count { get; set; }

    [Option(HelpText="Name for greeting")]
    public string Name { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

We need to specify the [Option] attribute on our two properties. This lets CommandLineParser know which properties are valid for parsing against the user input. Notice that Count option has c for its ShortName and count for its LongName. This lets you specify count input as either -c 10 or --count 10.

Let us just take the Count option to generate a sum of all whole numbers upto Count and display a exit message if the Name option is specified.

private static void ProcessOptions(Options options)
{
    int sum = 0;
    for (int i = 1; i <= options.Count; i++)
    {
        sum = sum + i;
    }
    Console.WriteLine($"Sum: {sum}");

    if(!string.IsNullOrEmpty(options.Name))
        Console.WriteLine($"Bye, {options.Name}");
}
Enter fullscreen mode Exit fullscreen mode

To run the program use, dotnet run command.

$ dotnet run -- --count 10 --name=animesh
Sum: 55
Bye, animesh
Enter fullscreen mode Exit fullscreen mode

If you want to run the compiled program directly, you can run dotnet command and pass the name of the output dll.

$ dotnet bin/Debug/netcoreapp2.2/netcore-test-cli.dll -c 123
Sum: 7626
Enter fullscreen mode Exit fullscreen mode

To make it a proper Linux executable, we need to publish the program with appropriate runtime identifier.

$ dotnet publish -c 'release' -r 'linux-x64'

Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 55.08 ms for /home/animesh/projects/lucubrations/netcore-test-cli/netcore-test-cli.csproj.
  netcore-test-cli -> /home/animesh/projects/lucubrations/netcore-test-cli/bin/release/netcoreapp2.2/linux-x64/netcore-test-cli.dll
  netcore-test-cli -> /home/animesh/projects/lucubrations/netcore-test-cli/bin/release/netcoreapp2.2/linux-x64/publish/
Enter fullscreen mode Exit fullscreen mode

This publishes the program to folder bin/Release/netcoreapp2.2/linux-x64. Check it out.

$ ll bin/Release/netcoreapp2.2/linux-x64

total 1552
-rwxrw-rw- 1 animesh animesh 692128 Jan 18 03:54 libhostfxr.so
-rwxrw-rw- 1 animesh animesh 712624 Jan 18 03:54 libhostpolicy.so
-rwxrw-rw- 1 animesh animesh 106912 Mar  9 15:29 netcore-test-cli
-rw-r--r-- 1 animesh animesh  37340 Mar  9 15:29 netcore-test-cli.deps.json
-rw-r--r-- 1 animesh animesh   5632 Mar  9 15:29 netcore-test-cli.dll
-rw-r--r-- 1 animesh animesh    928 Mar  9 15:29 netcore-test-cli.pdb
-rw-r--r-- 1 animesh animesh    206 Mar  9 15:29 netcore-test-cli.runtimeconfig.dev.json
-rw-r--r-- 1 animesh animesh     26 Mar  9 15:29 netcore-test-cli.runtimeconfig.json
drwxr-xr-x 2 animesh animesh  12288 Mar  9 15:29 publish
Enter fullscreen mode Exit fullscreen mode

Notice the file attributes on the third item netcore-test-cli in the directory listing above. It has file attributes -rwxrw-rw-, which means it is a Linux executable. This became possible as we specified the linux-x64 runtime identifier.

We can run the executable just as before.

$ cd bin/Release/netcoreapp2.2/linux-x64

$ ./netcore-test-cli 

Sum: 0

$ ./netcore-test-cli -c 100

Sum: 5050
Enter fullscreen mode Exit fullscreen mode

Both parameters specified:

$ ./netcore-test-cli -c 1000 --name animesh

Sum: 500500
Bye, animesh
Enter fullscreen mode Exit fullscreen mode

Specifying the --help option shows all possible options for user input:

$ ./netcore-test-cli --help

netcore-test-cli 1.0.0
Copyright (C) 2019 netcore-test-cli

  -c, --count    The count variable

  --name         Name for greeting

  --help         Display this help screen.

  --version      Display version information.

Enter fullscreen mode Exit fullscreen mode

That's the end of this post. We have seen how to build a basic command line application with .NET Core.

All code for this post is available on my gitlab repository.


Originally posted on my blog @ https://animesh.blog/build-a-linux-cli-app-with-net-core/

💖 💪 🙅 🚩
animesh
Animesh Bulusu

Posted on May 14, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Build a Linux CLI app with .NET Core
dotnetcore Build a Linux CLI app with .NET Core

May 14, 2019