Why is C# app not aborted despite the required global option missing?

54 views Asked by At

I have difficulties understanding how the System.CommandLine works and have prepared a short .Net fiddle to demonstrate my issue.

I am trying to create a C# console app, which would be called with --nodes option and be passed one or many numerical ids:

public static async Task Main(string[] args)
{
    Option<long[]> nodesOption = new("-n", "--nodes")
    {
        Arity = ArgumentArity.OneOrMore,
        Description = "Numerical node ids",
        IsRequired = true,
    };

    RootCommand rootCommand = new("A test app for saving node ids");
    rootCommand.AddGlobalOption(nodesOption);
    await rootCommand.InvokeAsync(args);

    Console.WriteLine("Why is this line printed?");
}

When I call the above code however without specifying any options, it does print the warning Option '-n' is required., but the execution is not aborted.

Shouldn't the app exit with code 1 when an isRequired global option is missing?

If it shouldn't, how can I change the app behaviour to exit with code 1?

And also I wonder, how to specify a new[] { 1234567890 } as the default value for the option, I cannot find it in the System.CommandLine doc.

Below is a screenshot of my test case and its output:

screenshot with C# code

1

There are 1 answers

1
AgentFire On BEST ANSWER

Yes, the execution of a command is not supposed to terminate the whole application, that is by design of the command-linetoolset.

Now, for the detecting. The rootCommand.InvokeAsync method would return non-zero result if not completed successfully. So, in your case simply check for the output:

int result = await rootCommand.InvokeAsync(args);

if (result != 0)
{
    // Handle the failure of the rootCommand's call.
    return;
}

As for the default value, there is actually an overload which allows you to specify a delegate which in turn should provide default values if none are input by the user:

Option<long[]> nodesOption = new(
    new[] { "-n", "--nodes" }, // Your aliases
    () => new[] { 1234567890L } // The delegate with the default values.
)