How to handle termination in System.CommandLine


System.CommandLine is currently in PREVIEW, and this documentation is for version 2.0 beta 4. Some information relates to prerelease product that may be substantially modified before it's released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

To handle termination, inject a CancellationToken instance into your handler code. This token can then be passed along to async APIs that you call from within your handler, as shown in the following example:

static async Task<int> Main(string[] args)
    int returnCode = 0;

    var urlOption = new Option<string>("--url", "A URL.");

    var rootCommand = new RootCommand("Handle termination example");

    rootCommand.SetHandler(async (context) =>
            string? urlOptionValue = context.ParseResult.GetValueForOption(urlOption);
            var token = context.GetCancellationToken();
            returnCode = await DoRootCommand(urlOptionValue, token);

    await rootCommand.InvokeAsync(args);

    return returnCode;

public static async Task<int> DoRootCommand(
    string? urlOptionValue, CancellationToken cancellationToken)
        using (var httpClient = new HttpClient())
            await httpClient.GetAsync(urlOptionValue, cancellationToken);
        return 0;
    catch (OperationCanceledException)
        Console.Error.WriteLine("The operation was aborted");
        return 1;

The preceding code uses a SetHandler overload that gets an InvocationContext instance rather than one or more IValueDescriptor<T> objects. The InvocationContext is used to get the CancellationToken and ParseResult objects. ParseResult can provide argument or option values.

Cancellation actions can also be added directly using the CancellationToken.Register method.

For information about an alternative way to set the process exit code, see Set exit codes.

See also

System.CommandLine overview