Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ważne
System.CommandLine
jest obecnie dostępna w wersji zapoznawczej, a ta dokumentacja dotyczy wersji 2.0 beta 5.
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed jego wydaniem. Firma Microsoft nie udziela żadnych gwarancji, wyraźnych ani domniemanych, w odniesieniu do podanych tutaj informacji.
System.CommandLine Zapewnia wyraźną separację między analizowaniem wiersza polecenia i wywołaniem akcji. Proces analizowania jest odpowiedzialny za analizowanie danych wejściowych wiersza polecenia i tworzenie System.CommandLine.ParseResult
obiektu zawierającego przeanalizowane wartości (i analizowanie błędów). Proces wywołania akcji jest odpowiedzialny za wywoływanie akcji skojarzonej z analizowaną poleceniem, opcją lub dyrektywą (argumenty nie mogą mieć akcji).
W poniższym przykładzie z samouczka Rozpoczynanie pracy z System.CommandLine, ParseResult
jest tworzony przez analizowanie wprowadzonych danych wiersza poleceń. Żadne akcje nie są zdefiniowane ani wywoływane:
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);
}
}
}
Akcja jest wywoływana, gdy dane polecenie (lub dyrektywa lub opcja) jest analizowane pomyślnie. Akcja jest delegatem, który przyjmuje System.CommandLine.ParseResult
parametr i zwraca int
kod zakończenia ( dostępne są również akcje asynchroniczne)). Kod zakończenia jest zwracany przez metodę System.CommandLine.Parsing.ParseResult.Invoke
i może służyć do wskazania, czy polecenie zostało wykonane pomyślnie, czy nie.
W poniższym przykładzie z samouczka Rozpoczynanie pracy z System.CommandLine, akcja jest definiowana dla głównego polecenia i wywoływana po przeanalizowaniu wejścia wiersza poleceń.
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);
}
}
}
Niektóre wbudowane symbole, takie jak System.CommandLine.Help.HelpOption
, System.CommandLine.VersionOption
lub System.CommandLine.Completions.SuggestDirective
, są dostarczane ze wstępnie zdefiniowanymi akcjami. Te symbole są automatycznie dodawane do głównego polecenia podczas jego tworzenia, a gdy wywołujesz polecenie System.CommandLine.Parsing.ParseResult
, działają bez problemu. Użycie akcji umożliwia skoncentrowanie się na logice aplikacji, a biblioteka zajmuje się analizowaniem i wywoływaniem akcji dla wbudowanych symboli. Jeśli wolisz, możesz trzymać się procesu analizowania i nie definiować żadnych akcji (jak w pierwszym przykładzie powyżej).
WynikAnalizy
Typ System.CommandLine.Parsing.ParseResult
jest klasą reprezentującą wyniki analizowania danych wejściowych wiersza polecenia. Należy go użyć, aby uzyskać przeanalizowane wartości dla opcji i argumentów (niezależnie od tego, czy używasz akcji, czy nie). Możesz również sprawdzić, czy wystąpiły błędy analizy lub niedopasowane tokeny.
GetValue
Metoda System.CommandLine.Parsing.ParseResult.GetValue<T>
umożliwia pobranie wartości opcji i argumentów:
int integer = parseResult.GetValue(delayOption);
string? message = parseResult.GetValue(messageOption);
Można również uzyskać wartości według nazwy, ale wymaga to określenia typu wartości, którą chcesz uzyskać.
W poniższym przykładzie użyto inicjatorów kolekcji języka C#, aby utworzyć polecenie główne:
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."
}
};
Następnie używa metody GetValue
, aby uzyskać wartości według nazwy.
rootCommand.SetAction(parseResult =>
{
int integer = parseResult.GetValue<int>("--delay");
string? message = parseResult.GetValue<string>("--message");
DisplayIntAndString(integer, message);
});
To przeciążenie GetValue
pobiera przeanalizowaną lub domyślną wartość dla określonej nazwy symbolu w kontekście przeanalizowanego polecenia (nie całego drzewa symboli). Akceptuje ona nazwę symbolu, a nie alias.
Analizowanie błędów
Właściwość System.CommandLine.Parsing.ParseResult.Errors
zawiera listę błędów analizy, które wystąpiły podczas procesu analizowania. Każdy błąd jest reprezentowany przez System.CommandLine.Parsing.ParseError
obiekt, który zawiera informacje o błędzie, takie jak komunikat o błędzie i token, który spowodował błąd.
Podczas wywoływania System.CommandLine.Parsing.ParseResult.Invoke
metody zwraca kod zakończenia wskazujący, czy analizowanie zakończyło się pomyślnie, czy nie. Jeśli wystąpiły jakiekolwiek błędy analizy, kod zakończenia jest inny niż zero, a wszystkie błędy analizy są drukowane do standardowego błędu.
Jeśli nie wywołasz System.CommandLine.Parsing.ParseResult.Invoke
metody, musisz samodzielnie obsłużyć błędy, na przykład przez ich wydrukowanie:
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
Niedopasowane tokeny
Właściwość System.CommandLine.Parsing.ParseResult.UnmatchedTokens
zawiera listę tokenów, które zostały przeanalizowane, ale nie były zgodne z żadnym skonfigurowanym poleceniem, opcją lub argumentem.
Lista niezgodnych tokenów jest przydatna w poleceniach, które działają jak osłony. Polecenie opakowujące pobiera zestaw tokenów i przekazuje je do innego polecenia lub aplikacji. Polecenie sudo
w systemie Linux jest przykładem. Pobiera nazwę użytkownika, aby personifikować, a następnie polecenie do uruchomienia. Przykład:
sudo -u admin apt update
Ten wiersz polecenia uruchomi apt update
polecenie jako użytkownik admin
.
Aby zaimplementować komendę otoczki podobną do tej, ustaw właściwość System.CommandLine.Command.TreatUnmatchedTokensAsErrors
komendy na false
.
System.CommandLine.Parsing.ParseResult.UnmatchedTokens
Następnie właściwość będzie zawierać wszystkie argumenty, które nie należą jawnie do polecenia . W poprzednim przykładzie ParseResult.UnmatchedTokens
zawierałby tokeny apt
i update
.
Czynności
Akcje to delegaty, które są wywoływane, gdy polecenie (lub opcja, lub dyrektywa) jest pomyślnie parsowane. Przyjmują parametr System.CommandLine.ParseResult
i zwracają kod zakończenia int
(lub Task<int>
). Kod zakończenia służy do wskazywania, czy akcja została wykonana pomyślnie, czy nie.
System.CommandLine udostępnia abstrakcyjną klasę System.CommandLine.CommandLineAction
bazową i dwie klasy pochodne: System.CommandLine.SynchronousCommandLineAction
i System.CommandLine.AsynchronousCommandLineAction
. Pierwszy jest używany do synchronicznych akcji, które zwracają int
kod zakończenia, podczas gdy ten ostatni jest używany do asynchronicznych akcji, które zwracają Task<int>
kod zakończenia.
Nie musisz tworzyć typu pochodnego, aby zdefiniować akcję. Możesz użyć System.CommandLine.Command.SetAction
metody , aby ustawić akcję dla polecenia. Akcja synchroniczna może być delegatem System.CommandLine.ParseResult
, który przyjmuje parametr i zwraca int
kod zakończenia. Delegatem asynchronicznym może być akcja, która przyjmuje parametry \System.CommandLine.ParseResult
i \CancellationToken, i zwraca \Task<int>
.
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
Akcje asynchroniczne
Akcje synchroniczne i asynchroniczne nie powinny być mieszane w tej samej aplikacji. Jeśli chcesz używać akcji asynchronicznych, aplikacja musi być asynchroniczna od góry do dołu. Oznacza to, że wszystkie akcje powinny być asynchroniczne i należy użyć System.CommandLine.Command.SetAction
metody akceptującej delegata zwracającego Task<int>
kod zakończenia. Ponadto CancellationToken przekazany delegatowi akcji musi zostać przekazany dalej do wszystkich metod, które można anulować, takich jak operacje wejściowo-wyjściowe plików lub żądania w sieci.
Oprócz tego należy upewnić się, że System.CommandLine.Parsing.ParseResult.InvokeAsync
metoda jest używana zamiast System.CommandLine.Parsing.ParseResult.Invoke
. Ta metoda jest asynchroniczna i zwraca Task<int>
kod zakończenia. Akceptuje również opcjonalny CancellationToken parametr, który może służyć do anulowania akcji.
Powyższy kod używa przeciążenia SetAction
, które pobiera ParseResult oraz CancellationToken, zamiast tylko 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;
}
}
Limit czasu zakończenia procesu
System.CommandLine.CommandLineConfiguration.ProcessTerminationTimeout
umożliwia sygnalizowanie i obsługę zakończenia procesu (Ctrl+C, SIGINT
, SIGTERM
) poprzez CancellationToken przekazywany do każdej akcji asynchronicznej podczas wywołania. Jest ona domyślnie włączona (2 sekundy), ale można ją ustawić tak, null
aby ją wyłączyć.
Po włączeniu tej akcji, jeśli akcja nie zostanie ukończona w określonym przedziale czasu, proces zostanie zakończony. Jest to przydatne do łagodnego zarządzania zakończeniem procesu, na przykład przez zapisanie stanu przed jego zakończeniem.
Aby przetestować przykładowy kod z poprzedniego akapitu, uruchom polecenie z adresem URL, który potrwa chwilę, a przed zakończeniem ładowania naciśnij Ctrl+C. W systemie macOS naciśnij Command+Period(.). Przykład:
testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted
Kody zakończenia
Kod zakończenia to wartość całkowita zwracana przez akcję wskazującą jej powodzenie lub niepowodzenie. Zgodnie z konwencją, kod wyjścia 0
oznacza powodzenie, podczas gdy dowolna wartość niezerowa wskazuje błąd. Ważne jest, aby zdefiniować znaczące kody zakończenia w aplikacji, aby wyraźnie przekazać stan wykonywania polecenia.
Każda metoda SetAction
ma przeciążenie, które akceptuje delegata zwracającego kod zakończenia int
, gdzie kod zakończenia musi być podany w sposób jawny, oraz przeciążenie zwracające wartość 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();
}
Zobacz także
Jak dostosować analizowanie i walidację w programie System.CommandLineSystem.CommandLine przegląd