Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
System.CommandLine bietet eine klare Trennung zwischen Befehlszeilenanalyse und Aktionsaufruf. Der Analyseprozess ist für die Analyse von Befehlszeileneingaben und das Erstellen eines ParseResult Objekts verantwortlich, das die analysierten Werte (und Analysefehler) enthält. Der Aktionsaufrufprozess ist für das Aufrufen der Aktion verantwortlich, die dem analysierten Befehl, der Option oder der Direktive zugeordnet ist (Argumente können keine Aktionen haben).
Im folgenden Beispiel aus dem Lernprogramm " Erste Schritte" System.CommandLine wird die ParseResult Durchanalyse der Befehlszeileneingabe erstellt. Es sind keine Aktionen definiert oder aufgerufen:
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.Errors.Count == 0 && 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);
}
}
}
Eine Aktion wird aufgerufen, wenn ein bestimmter Befehl (oder eine Direktive oder Option) erfolgreich analysiert wird. Die Aktion ist ein Delegat, der ein ParseResult Argument annimmt und einen int Exitcode zurückgibt (asynchrone Aktionen sind ebenfalls verfügbar). Der Beendigungscode wird von der ParseResult.Invoke(InvocationConfiguration) Methode zurückgegeben und kann verwendet werden, um anzugeben, ob der Befehl erfolgreich ausgeführt wurde oder nicht.
Im folgenden Beispiel aus dem Lernprogramm " Erste Schritte" System.CommandLine wird die Aktion für den Stammbefehl definiert und nach der Analyse der Befehlszeileneingabe aufgerufen:
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);
}
}
}
Einige integrierte Symbole, z HelpOption. B. , VersionOptionund SuggestDirective, enthalten vordefinierte Aktionen. Diese Symbole werden automatisch dem Stammbefehl hinzugefügt, wenn Sie ihn erstellen, und wenn Sie die ParseResultSymbole aufrufen, funktionieren sie einfach. Mithilfe von Aktionen können Sie sich auf Ihre App-Logik konzentrieren, während die Bibliothek die Analyse und Das Aufrufen von Aktionen für integrierte Symbole übernimmt. Wenn Es Ihnen lieber ist, können Sie den Analyseprozess beibehalten und keine Aktionen definieren (wie im ersten Beispiel in diesem Artikel).
ParseResult
Die ParseResult Klasse stellt die Ergebnisse der Analyse der Befehlszeileneingabe dar. Sie müssen sie verwenden, um die analysierten Werte für Optionen und Argumente abzurufen (unabhängig davon, ob Sie Aktionen verwenden oder nicht). Sie können auch überprüfen, ob Analysefehler oder nicht übereinstimmende Token vorhanden sind.
Wert abrufen
Mit der ParseResult.GetValue Methode können Sie die Werte von Optionen und Argumenten abrufen:
int integer = parseResult.GetValue(delayOption);
string? message = parseResult.GetValue(messageOption);
Sie können Werte auch anhand des Namens abrufen, dies erfordert jedoch, dass Sie den Typ des abzurufenden Werts angeben.
Im folgenden Beispiel werden C#-Sammlungsinitialisierer zum Erstellen eines Stammbefehls verwendet:
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."
}
};
Anschließend wird die GetValue Methode verwendet, um die Werte anhand des Namens abzurufen:
rootCommand.SetAction(parseResult =>
{
int integer = parseResult.GetValue<int>("--delay");
string? message = parseResult.GetValue<string>("--message");
DisplayIntAndString(integer, message);
});
Diese Überladung von GetValue ruft den geparsten oder den Standardwert für den angegebenen Symbolnamen ab, und zwar im Kontext des geparsten Befehls (nicht des gesamten Symbolbaums). Er akzeptiert den Symbolnamen, nicht einen Alias.
Analysefehler
Die ParseResult.Errors Eigenschaft enthält eine Liste der Analysefehler, die während des Analysevorgangs aufgetreten sind. Jeder Fehler wird durch ein ParseError Objekt dargestellt, das Informationen zum Fehler enthält, z. B. die Fehlermeldung und das Token, das den Fehler verursacht hat.
Wenn Sie die ParseResult.Invoke(InvocationConfiguration) Methode aufrufen, wird ein Exitcode zurückgegeben, der angibt, ob die Analyse erfolgreich war oder nicht. Bei Parse-Fehlern ist der Exit Code ungleich Null und alle Parse-Fehler werden in den Standardfehler ausgegeben.
Wenn Sie die ParseResult.Invoke Methode nicht aufrufen, müssen Sie die Fehler selbst behandeln, z. B. durch Drucken:
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
Nicht übereinstimmende Token
Die UnmatchedTokens Eigenschaft enthält eine Liste der Token, die analysiert wurden, aber keinem konfigurierten Befehl, einer Option oder einem Argument entsprechen.
Die Liste der nicht übereinstimmenden Token ist bei Befehlen nützlich, die sich wie Wrapper verhalten. Ein Wrapperbefehl verwendet eine Reihe von Token und leitet sie an einen anderen Befehl oder eine andere App weiter. Der sudo Befehl in Linux ist ein Beispiel. Er benötigt den Namen eines Benutzers, zu dessen Identität er wechseln soll, gefolgt von einem auszuführenden Befehl. Beispielsweise führt der folgende Befehl den apt update Befehl als Benutzer adminaus:
sudo -u admin apt update
Um einen Wrapperbefehl wie diesen zu implementieren, legen Sie die Befehlseigenschaft System.CommandLine.Command.TreatUnmatchedTokensAsErrors auf false. Dann enthält die System.CommandLine.Parsing.ParseResult.UnmatchedTokens Eigenschaft alle Argumente, die nicht explizit zum Befehl gehören. Im vorherigen Beispiel würde ParseResult.UnmatchedTokens die Tokens apt und update enthalten.
Aktionen
Aktionen sind Stellvertretungen, die aufgerufen werden, wenn ein Befehl (oder eine Option oder eine Direktive) erfolgreich analysiert wird. Sie nehmen ein ParseResult Argument und geben einen int (oder Task<int>) Ausgangscode zurück. Der Beendigungscode wird verwendet, um anzugeben, ob die Aktion erfolgreich ausgeführt wurde oder nicht.
System.CommandLine stellt eine abstrakte Basisklasse CommandLineAction und zwei abgeleitete Klassen bereit: SynchronousCommandLineAction und AsynchronousCommandLineAction. Der erste Wird für synchrone Aktionen verwendet, die einen int Exitcode zurückgeben, während letztere für asynchrone Aktionen verwendet wird, die einen Task<int> Ausgangscode zurückgeben.
Sie müssen keinen abgeleiteten Typ erstellen, um eine Aktion zu definieren. Mit der SetAction Methode können Sie eine Aktion für einen Befehl festlegen. Bei der synchronen Aktion kann es sich um einen Delegaten handeln, der ein ParseResult Argument akzeptiert und einen int Ausgangscode zurückgibt. Die asynchrone Aktion kann ein Delegat sein, der verwendet und Argumente verwendet ParseResult und ein CancellationToken.Task<int>
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
Asynchrone Aktionen
Synchrone und asynchrone Aktionen sollten nicht in derselben Anwendung gemischt werden. Wenn Sie asynchrone Aktionen verwenden möchten, muss Ihre Anwendung asynchron sein. Dies bedeutet, dass alle Aktionen asynchron sein sollten, und Sie sollten die SetAction Methode verwenden, die einen Delegaten akzeptiert, der einen Task<int> Ausgangscode zurückgibt. Darüber hinaus muss der CancellationToken an den Aktionsdelegat übergebene Delegat weiter an alle Methoden übergeben werden, die abgebrochen werden können, z. B. Datei-E/A-Vorgänge oder Netzwerkanforderungen.
Sie müssen auch sicherstellen, dass die ParseResult.InvokeAsync(InvocationConfiguration, CancellationToken) Methode anstelle von Invoke. Diese Methode ist asynchron und gibt einen Task<int> Ausgangscode zurück. Sie akzeptiert auch einen optionalen CancellationToken Parameter, der zum Abbrechen der Aktion verwendet werden kann.
Der folgende Code verwendet eine SetAction Überladung, die ein ParseResult und nicht CancellationToken nur folgendes ParseResultabruft:
static Task<int> Main(string[] args)
{
Option<string> urlOption = new("--url")
{
Description = "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;
}
}
Timeout für die Beendigung des Prozesses
ProcessTerminationTimeout ermöglicht die Signalisierung und Verarbeitung der Prozessbeendigung (STRG+C, SIGINT, SIGTERM) über eine CancellationToken Aktion, die während des Aufrufs an jede asynchrone Aktion übergeben wird. Standardmäßig ist es aktiviert (2 Sekunden), aber Sie können es auf null festlegen, um es zu deaktivieren.
Wenn aktiviert, wird der Prozess beendet, falls die Aktion nicht innerhalb des angegebenen Timeouts abgeschlossen ist. Dies ist nützlich, um die Beendigung ordnungsgemäß zu behandeln, z. B. durch Speichern des Zustands, bevor der Prozess beendet wird.
Um den Beispielcode aus dem vorherigen Absatz zu testen, führen Sie den Befehl mit einer URL aus, die einen Moment zum Laden benötigt, und drücken Sie STRG+C, bevor der Ladevorgang abgeschlossen ist. Unter macOS drücken Sie Befehl+Periode(.). Beispiel:
testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted
Exitcodes
Der Ausgangscode ist ein ganzzahliger Wert, der von einer Aktion zurückgegeben wird, die den Erfolg oder Fehler angibt. Ein Exit Code von 0 bedeutet gemäß der Konvention Erfolg, während jeder Wert ungleich Null einen Fehler anzeigt. Es ist wichtig, aussagekräftige Exitcodes in Ihrer Anwendung zu definieren, um den Status der Befehlsausführung klar zu kommunizieren.
Jede SetAction Methode verfügt über eine Überladung, die einen Delegaten akzeptiert, der einen int Exitcode zurückgibt, wobei der Exitcode explizit bereitgestellt werden muss, und eine Überladung, die 0 zurückgibt.
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();
}