Table of Contents

Method ConfigureCommandApp

Namespace
Ploch.CommandLine.Spectre
Assembly
Ploch.CommandLine.Spectre.dll

ConfigureCommandApp(Action<IConfigurator>)

Builds and configures the command-line application.

public ICommandAppExecutor ConfigureCommandApp(Action<IConfigurator> configurator)

Parameters

configurator Action<IConfigurator>

Command line application configurator used to configure the commands and options.

Returns

ICommandAppExecutor

An instance of ICommandAppExecutor allowing execution of the app.

Remarks

The returned executor permits one execution attempt: an attempt may build the host behind it and Build() cannot be called again, so every attempt consumes the executor and a second Run(params IEnumerable<string>) or RunAsync(params IEnumerable<string>) on it throws InvalidOperationException. Call this method again to build a fresh executor for another run; it replays the same recorded configuration over the same cancellation source. Cancellation is permanent, so after an attempt that was cancelled - by Ctrl+C or through the registered CancellationTokenSource - this method throws InvalidOperationException rather than hand out an executor whose every command would start with an already-cancelled token. To run again after cancellation, start from a new builder (Create(params IEnumerable<string>)) or pass a fresh source to the constructor.

Unless ShowBanner(bool) was switched off, this call writes the start-up banner to standard error — so it precedes Spectre's own help and version output too — and registers the Spectre.Console.Cli.ICommandInterceptor that writes the "Executing command" line to standard error before each command. That interceptor is registered first, before the services bundles and the caller's delegates, so it runs before any interceptor the caller registers, through a bundle, ConfigureServices(Action<IServiceCollection>) or Spectre's SetInterceptor. A default command is announced as "the default command".

Every ConfigureServices(Action<HostBuilderContext, IServiceCollection>), ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder>) and ConfigureHost(Action<IHostBuilder>) call is applied to the host builder in the order the calls were made, so the fluent chain reads the way it executes. Of two service registrations for the same service, the one from the later call wins, whether it was made through ConfigureServices or through ConfigureServices(Action<HostBuilderContext, IServiceCollection>) inside a ConfigureHost(Action<IHostBuilder>) delegate. Likewise for two application configuration sources supplying the same key, made through ConfigureAppConfiguration or through ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder>) inside ConfigureHost(Action<IHostBuilder>).

Call order decides precedence between delegates of the same kind only. The host builder still runs its phases in its own fixed order, whatever order the calls were recorded in: host configuration (ConfigureHostConfiguration(Action<IConfigurationBuilder>)), then application configuration, then services, then ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder>). So an application configuration source always overrides a host configuration source for the same key, and a container delegate always runs after every service delegate.

The builder's own defaults sit outside that sequence. The default host configuration sources — appsettings.json, appsettings.{Environment}.json, user secrets in Development, environment variables and the command-line arguments, in ascending precedence — are added before any caller application configuration source, and the registered services bundles are configured before any caller service registration, so a caller can override both. The application's CancellationTokenSource is registered after every caller service delegate, so no ConfigureServices call can replace it; only a container delegate or a custom service provider factory, which run later still, could. The token handed to running commands always comes from the builder's own source, whatever the container holds.

The application exits with the codes ExitCode documents. A command line Spectre.Console.Cli cannot parse or bind, and settings that fail validation, are reported by Spectre as before but exit with InvalidInput rather than Spectre's own -1; an exception that escapes a command not derived from AppCommand<TSettings> or AsyncAppCommand<TSettings> goes to the registered IExceptionHandler, whose return value is the exit code; and a failure before the host exists - one thrown while building it - is reported and exits with Error. The handler that does this is set before configurator runs, so a SetExceptionHandler or PropagateExceptions call in the delegate replaces it. Two of Spectre's own early returns are unchanged: a branch invoked without a sub-command, and a default command invoked without its required arguments, both show help and return 1.

The host is built once a run of the returned executor has parsed its arguments and resolves the command — a parse failure or --version returns before any host exists — and it exists for dependency injection, configuration and logging only: the library never starts it. A CLI command is the unit of work, so StartAsync(CancellationToken) is not called, and an IHostedService registered through ConfigureServices — with AddHostedService, for instance — has neither its StartAsync(CancellationToken) nor its StopAsync(CancellationToken) invoked by the library. A host that was built is disposed when the run ends. Starting the host around the command is a possible 1.x feature, tracked as PLO-785.

Exceptions

ArgumentNullException

Thrown when configurator is null.

ObjectDisposedException

Thrown when the builder has been disposed.

InvalidOperationException

Thrown when the application info has no name, or when the builder's CancellationTokenSource has already been cancelled.