Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Importante
System.CommandLine
actualmente está en versión preliminar y esta documentación es para la versión 2.0 beta 5.
Cierta información se relaciona con el producto de versión preliminar que puede modificarse sustancialmente antes de su lanzamiento. Microsoft no ofrece ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
System.CommandLine proporciona una separación clara entre el análisis de línea de comandos y la invocación de acción. El proceso de análisis es responsable de analizar la entrada de la línea de comandos y crear un System.CommandLine.ParseResult
objeto que contenga los valores analizados (y analizar errores). El proceso de invocación de acción es responsable de invocar la acción asociada al comando analizado, la opción o la directiva (los argumentos no pueden tener acciones).
En el ejemplo siguiente de nuestro tutorial Introducción System.CommandLine , ParseResult
se crea mediante el análisis de la entrada de la línea de comandos. No se definen ni invocan acciones:
using System.CommandLine;
using System.CommandLine.Parsing;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "The file to read and display on the console."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
rootCommand.Options.Add(fileOption);
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
ReadFile(parsedFile);
return 0;
}
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
}
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
}
Se invoca una acción cuando se analiza correctamente un comando determinado (o directiva o opción). La acción es un delegado que toma un System.CommandLine.ParseResult
parámetro y devuelve un int
código de salida (también están disponibles las acciones asincrónicas). El método devuelve el System.CommandLine.Parsing.ParseResult.Invoke
código de salida y se puede usar para indicar si el comando se ejecutó correctamente o no.
En el ejemplo siguiente de nuestro tutorial Introducción System.CommandLine , la acción se define para el comando raíz e invoca después de analizar la entrada de la línea de comandos:
using System.CommandLine;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "The file to read and display on the console."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
rootCommand.Options.Add(fileOption);
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
ParseResult parseResult = rootCommand.Parse(args);
return parseResult.Invoke();
}
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
}
Algunos símbolos integrados, como System.CommandLine.Help.HelpOption
, System.CommandLine.VersionOption
o System.CommandLine.Completions.SuggestDirective
, vienen con acciones predefinidas. Estos símbolos se agregan automáticamente al comando raíz al crearlo y, al invocar , System.CommandLine.Parsing.ParseResult
solo funcionan. El uso de acciones permite centrarse en la lógica de la aplicación, mientras que la biblioteca se encarga del análisis y la invocación de acciones para símbolos integrados. Si lo prefiere, puede seguir el proceso de análisis y no definir ninguna acción (como en el primer ejemplo anterior).
ParseResult
El System.CommandLine.Parsing.ParseResult
tipo es una clase que representa los resultados del análisis de la entrada de la línea de comandos. Debe usarlo para obtener los valores analizados para las opciones y los argumentos (independientemente de si usa acciones o no). También puede comprobar si se han producido errores de análisis o tokens no coincidentes.
GetValue
El System.CommandLine.Parsing.ParseResult.GetValue<T>
método permite recuperar los valores de opciones y argumentos:
int integer = parseResult.GetValue(delayOption);
string? message = parseResult.GetValue(messageOption);
También puede obtener valores por nombre, pero esto requiere que especifique el tipo del valor que desea obtener.
En el ejemplo siguiente se usan inicializadores de colección de C# para crear un comando raíz:
RootCommand rootCommand = new("Parameter binding example")
{
new Option<int>("--delay")
{
Description = "An option whose argument is parsed as an int."
},
new Option<string>("--message")
{
Description = "An option whose argument is parsed as a string."
}
};
A continuación, usa el GetValue
método para obtener los valores por nombre:
rootCommand.SetAction(parseResult =>
{
int integer = parseResult.GetValue<int>("--delay");
string? message = parseResult.GetValue<string>("--message");
DisplayIntAndString(integer, message);
});
Esta sobrecarga de GetValue
obtiene el valor analizado o predeterminado para el nombre de símbolo especificado, en el contexto del comando analizado (no todo el árbol de símbolos). Acepta el nombre del símbolo, no un alias.
Análisis de errores
La System.CommandLine.Parsing.ParseResult.Errors
propiedad contiene una lista de errores de análisis que se produjeron durante el proceso de análisis. Cada error se representa mediante un System.CommandLine.Parsing.ParseError
objeto , que contiene información sobre el error, como el mensaje de error y el token que provocó el error.
Cuando se llama al System.CommandLine.Parsing.ParseResult.Invoke
método , devuelve un código de salida que indica si el análisis se realizó correctamente o no. Si se han producido errores de análisis, el código de salida no es cero y todos los errores de análisis se imprimen en el error estándar.
Si no invoca el System.CommandLine.Parsing.ParseResult.Invoke
método , debe controlar los errores por su cuenta, por ejemplo, imprimiéndolas:
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
Tokens no coincidentes
La System.CommandLine.Parsing.ParseResult.UnmatchedTokens
propiedad contiene una lista de los tokens analizados, pero que no coinciden con ningún comando, opción o argumento configurado.
La lista de tokens no coincidentes es útil en los comandos que se comportan como contenedores. Un comando contenedor toma un conjunto de tokens y los reenvía a otro comando o aplicación. El sudo
comando en Linux es un ejemplo. Toma el nombre de un usuario para suplantar seguido de un comando que se va a ejecutar. Por ejemplo:
sudo -u admin apt update
Esta línea de comandos ejecutaría el apt update
comando como el usuario admin
.
Para implementar un comando contenedor como este, establezca la propiedad System.CommandLine.Command.TreatUnmatchedTokensAsErrors
false
command en . A continuación, la System.CommandLine.Parsing.ParseResult.UnmatchedTokens
propiedad contendrá todos los argumentos que no pertenecen explícitamente al comando. En el ejemplo anterior, ParseResult.UnmatchedTokens
contendrá los apt
tokens y update
.
Acciones
Las acciones son delegados que se invocan cuando se analiza correctamente un comando (o una opción o una directiva). Toman un parámetro y devuelven un System.CommandLine.ParseResult
int
código de salida (o Task<int>
). El código de salida se usa para indicar si la acción se ejecutó correctamente o no.
System.CommandLine proporciona una clase System.CommandLine.CommandLineAction
base abstracta y dos clases derivadas: System.CommandLine.SynchronousCommandLineAction
y System.CommandLine.AsynchronousCommandLineAction
. El primero se usa para acciones sincrónicas que devuelven un int
código de salida, mientras que el último se usa para acciones asincrónicas que devuelven un Task<int>
código de salida.
No es necesario crear un tipo derivado para definir una acción. Puede usar el System.CommandLine.Command.SetAction
método para establecer una acción para un comando. La acción sincrónica puede ser un delegado que toma un System.CommandLine.ParseResult
parámetro y devuelve un int
código de salida. La acción asincrónica puede ser un delegado que toma un System.CommandLine.ParseResult
parámetro y CancellationToken y devuelve un Task<int>
.
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
Acciones asincrónicas
Las acciones sincrónicas y asincrónicas no deben mezclarse en la misma aplicación. Si desea usar acciones asincrónicas, la aplicación debe ser asincrónica desde la parte superior a la inferior. Esto significa que todas las acciones deben ser asincrónicas y debe usar el System.CommandLine.Command.SetAction
método que acepta un delegado que devuelve un Task<int>
código de salida. Además, el CancellationToken objeto que se pasa al delegado de acción debe pasarse más allá a todos los métodos que se pueden cancelar, como las operaciones de E/S de archivos o las solicitudes de red.
Además, debe asegurarse de que el System.CommandLine.Parsing.ParseResult.InvokeAsync
método se usa en lugar de System.CommandLine.Parsing.ParseResult.Invoke
. Este método es asincrónico y devuelve un Task<int>
código de salida. También acepta un parámetro opcional CancellationToken que se puede usar para cancelar la acción.
El código anterior usa una sobrecarga que obtiene un SetAction
elemento ParseResult y un objeto CancellationToken en lugar de simplemente ParseResult
:
static Task<int> Main(string[] args)
{
Option<string> urlOption = new("--url", "A URL.");
RootCommand rootCommand = new("Handle termination example") { urlOption };
rootCommand.SetAction((ParseResult parseResult, CancellationToken cancellationToken) =>
{
string? urlOptionValue = parseResult.GetValue(urlOption);
return DoRootCommand(urlOptionValue, cancellationToken);
});
return rootCommand.Parse(args).InvokeAsync();
}
public static async Task<int> DoRootCommand(
string? urlOptionValue, CancellationToken cancellationToken)
{
using HttpClient httpClient = new();
try
{
await httpClient.GetAsync(urlOptionValue, cancellationToken);
return 0;
}
catch (OperationCanceledException)
{
await Console.Error.WriteLineAsync("The operation was aborted");
return 1;
}
}
Tiempo de espera de finalización del proceso
System.CommandLine.CommandLineConfiguration.ProcessTerminationTimeout
habilita la señalización y el control de la terminación del proceso (Ctrl+C, SIGINT
, SIGTERM
) a través de un CancellationToken objeto que se pasa a cada acción asincrónica durante la invocación. Está habilitado de forma predeterminada (2 segundos), pero puede establecerlo en null
para deshabilitarlo.
Cuando se habilita, si la acción no se completa dentro del tiempo de espera especificado, se finalizará el proceso. Esto resulta útil para controlar la terminación correctamente, por ejemplo, guardando el estado antes de que finalice el proceso.
Para probar el código de ejemplo del párrafo anterior, ejecute el comando con una dirección URL que tardará un momento en cargarse y antes de que termine de cargarse, presione Ctrl+C. En macOS, presione Command+Period(.). Por ejemplo:
testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted
Códigos de salida
El código de salida es un valor entero devuelto por una acción que indica su éxito o error. Por convención, un código de salida de 0
significa que se ha realizado correctamente, mientras que cualquier valor distinto de cero indica un error. Es importante definir códigos de salida significativos en la aplicación para comunicar claramente el estado de ejecución del comando.
Cada SetAction
método tiene una sobrecarga que acepta un delegado que devuelve un int
código de salida donde el código de salida debe proporcionarse de forma explícita y una sobrecarga que devuelve 0
.
static int Main(string[] args)
{
Option<int> delayOption = new("--delay");
Option<string> messageOption = new("--message");
RootCommand rootCommand = new("Parameter binding example")
{
delayOption,
messageOption
};
rootCommand.SetAction(parseResult =>
{
Console.WriteLine($"--delay = {parseResult.GetValue(delayOption)}");
Console.WriteLine($"--message = {parseResult.GetValue(messageOption)}");
// Value returned from the action delegate is the exit code.
return 100;
});
return rootCommand.Parse(args).Invoke();
}
Consulte también
Cómo personalizar el análisis y la validación en System.CommandLineSystem.CommandLine visión general