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.
Wichtig
System.CommandLine
befindet sich derzeit in der Vorschau, und diese Dokumentation bezieht sich auf die Version 2.0 beta 5.
Einige Informationen beziehen sich auf vorab veröffentlichte Produkte, die vor der Veröffentlichung erheblich geändert werden können. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
In diesem Lernprogramm wird gezeigt, wie Sie eine .NET-Befehlszeilen-App erstellen, die die System.CommandLine
Bibliothek verwendet. Sie beginnen mit dem Erstellen eines einfachen Stammbefehls, der über eine Option verfügt. Anschließend erstellen Sie auf dieser Basis eine komplexere App, die mehrere Unterbefehle und unterschiedliche Optionen für jeden Befehl enthält.
In diesem Tutorial lernen Sie Folgendes:
- Erstellen Sie Befehle, Optionen und Argumente.
- Geben Sie Standardwerte für Optionen an.
- Weisen Sie Befehlen Optionen und Argumente zu.
- Weisen Sie allen Unterbefehlen unter einem Befehl rekursiv eine Option zu.
- Arbeiten Sie mit mehreren Ebenen geschachtelter Unterbefehle.
- Erstellen Sie Aliase für Befehle und Optionen.
- Arbeiten Sie mit
string
,string[]
,int
,bool
,FileInfo
und enum Optionstypen. - Lesen von Optionswerten im Befehlsaktionscode.
- Verwenden Sie benutzerdefinierten Code zum Analysieren und Überprüfen von Optionen.
Voraussetzungen
- Das neueste .NET SDK
- Visual Studio Code-Editor
- Das C# DevKit
Oder
- Visual Studio 2022 mit installierter Workload .NET-Desktopentwicklung.
Erstellen der App
Erstellen Sie ein .NET 9-Konsolen-App-Projekt mit dem Namen "scl".
Erstellen Sie einen Ordner mit dem Namen "scl " für das Projekt, und öffnen Sie dann eine Eingabeaufforderung im neuen Ordner.
Führen Sie den folgenden Befehl aus:
dotnet new console --framework net9.0
Installieren Sie das System.CommandLine-Paket
Führen Sie den folgenden Befehl aus:
dotnet add package System.CommandLine --prerelease
Oder in .NET 10+:
dotnet package add System.CommandLine --prerelease
Die
--prerelease
Option ist erforderlich, da sich die Bibliothek noch in der Betaversion befindet.
Analysieren der Argumente
Ersetzen Sie den Inhalt von Program.cs durch den folgenden Code:
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); } } }
Der vorherige Code:
- Erstellt eine Option vom Typ
--file
, die FileInfo genannt wird, und fügt sie dem Stammbefehl hinzu.
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);
- Analysiert
args
und überprüft, ob ein beliebiger Wert für die Option--file
bereitgestellt wurde. Wenn dies der Fall ist, ruft sie dieReadFile
Methode mit analysierten Werten auf und gibt Exit-Code zurück0
:
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
ReadFile(parsedFile);
return 0;
}
- Wenn kein Wert für
--file
angegeben wurde, werden verfügbare Analysefehler ausgegeben und der Exit-Code1
zurückgegeben.
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
- Die
ReadFile
Methode liest die angegebene Datei und zeigt den Inhalt auf der Konsole an:
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
Testen der App
Sie können eine der folgenden Möglichkeiten zum Testen während der Entwicklung einer Befehlszeilen-App verwenden:
Führen Sie den
dotnet build
Befehl aus, und öffnen Sie dann eine Eingabeaufforderung im Ordner "scl/bin/Debug/net9.0 ", um die ausführbare Datei auszuführen:dotnet build cd bin/Debug/net9.0 scl --file scl.runtimeconfig.json
Verwenden Sie
dotnet run
, und übergeben Sie Optionswerte anstelle desrun
-Befehls an die App, indem Sie sie wie im folgenden Beispiel gezeigt nach--
einschließen:dotnet run -- --file bin/Debug/net9.0/scl.runtimeconfig.json
In diesem Lernprogramm wird davon ausgegangen, dass Sie die erste dieser Optionen verwenden.
Wenn Sie die App ausführen, wird der Inhalt der durch die --file
Option angegebenen Datei angezeigt.
{
"runtimeOptions": {
"tfm": "net9.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
}
}
}
Aber was passiert, wenn Sie es mit --help
auffordern, die Hilfe anzuzeigen? Auf der Konsole wird nichts ausgegeben, weil die App das Szenario, bei dem --file
nicht angegeben ist und keine Parsefehler vorliegen, noch nicht behandelt.
Analysieren sie die Argumente, und rufen Sie das ParseResult auf.
System.CommandLine ermöglicht es Ihnen, eine Aktion anzugeben, die aufgerufen wird, wenn ein bestimmtes Symbol (Befehl, Direktive oder Option) erfolgreich analysiert wird. Die Aktion ist ein Delegat, der einen System.CommandLine.ParseResult
Parameter verwendet und einen int
Exitcode zurückgibt (asynchrone Aktionen sind ebenfalls verfügbar). Der Beendigungscode wird von der System.CommandLine.Parsing.ParseResult.Invoke
Methode zurückgegeben und kann verwendet werden, um anzugeben, ob der Befehl erfolgreich ausgeführt wurde oder nicht.
Ersetzen Sie den Inhalt von Program.cs durch den folgenden Code:
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); } } }
Der vorherige Code:
Gibt die Methode an
ReadFile
, die aufgerufen wird, wenn der Stammbefehl aufgerufen wird:rootCommand.SetAction(parseResult => { FileInfo parsedFile = parseResult.GetValue(fileOption); ReadFile(parsedFile); return 0; });
Parst die
args
und ruft das Ergebnis auf:ParseResult parseResult = rootCommand.Parse(args); return parseResult.Invoke();
Wenn Sie die App ausführen, wird der Inhalt der durch die --file
Option angegebenen Datei angezeigt.
Was geschieht, wenn Sie sie bitten, die Hilfe anzuzeigen, indem Sie angeben --help
?
scl --help
Die folgende Ausgabe wird ausgegeben:
Description:
Sample app for System.CommandLine
Usage:
scl [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
--file The file to read and display on the conso
System.CommandLine.RootCommand
stellt standardmäßig Hilfeoption, Versionsoption und Vorschlagsdirektive bereit. ParseResult.Invoke
die Methode ist für das Aufrufen der Aktion des analysierten Symbols verantwortlich. Es kann sich entweder um die für unseren Befehl explizit definierte Aktion oder um die Hilfeaktion handeln, die durch System.CommandLine
für System.CommandLine.Help.HelpOption
definiert ist. Wenn es Parse-Fehler entdeckt, gibt es diese in den Standardfehler aus, gibt die Hilfe in die Standardausgabe aus und gibt einen 1
Exit-Code zurück:
scl --invalid bla
Unrecognized command or argument '--invalid'.
Unrecognized command or argument 'bla'.
Hinzufügen eines Unterbefehls und von Optionen
In diesem Abschnitt führen Sie Folgendes aus:
- Erstellen Sie weitere Optionen.
- Erstellen Sie einen Unterbefehl.
- Weisen Sie dem neuen Unterbefehl die neuen Optionen zu.
Mit den neuen Optionen können Sie die Vordergrund- und Hintergrundtextfarben und die Lesegeschwindigkeit konfigurieren. Diese Features werden verwendet, um eine Sammlung von Zitaten zu lesen, die aus dem Lernprogramm der Teleprompter-Konsolen-App stammen.
Kopieren Sie die sampleQuotes.txt Datei aus dem GitHub-Repository für dieses Beispiel in Ihr Projektverzeichnis. Informationen zum Herunterladen von Dateien finden Sie in den Anweisungen in Beispielen und Lernprogrammen.
Öffnen Sie die Projektdatei, und fügen Sie direkt vor dem schließenden
<ItemGroup>
Tag ein</Project>
Element hinzu:<ItemGroup> <Content Include="sampleQuotes.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup>
Wenn Sie dieses Markup hinzufügen, wird die Textdatei beim Erstellen der App in den Ordner "bin/debug/net9.0" kopiert. Wenn Sie also die ausführbare Datei in diesem Ordner ausführen, können Sie nach Namen auf die Datei zugreifen, ohne einen Ordnerpfad anzugeben.
Erstellen Sie in Program.cs nach dem Code, der die
--file
Option erstellt, Optionen zum Steuern der Lesegeschwindigkeit und der Textfarben:Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds per character in a line.", DefaultValueFactory = parseResult => 42 }; Option<ConsoleColor> fgcolorOption = new("--fgcolor") { Description = "Foreground color of text displayed on the console.", DefaultValueFactory = parseResult => ConsoleColor.White }; Option<bool> lightModeOption = new("--light-mode") { Description = "Background color of text displayed on the console: default is black, light mode is white." };
Löschen Sie nach der Zeile, die den Stammbefehl erstellt, den Code, der die
--file
Option hinzufügt. Sie entfernen es hier, da Sie ihn einem neuen Unterbefehl hinzufügen.Erstellen Sie nach der Zeile, die den Stammbefehl erstellt, einen
read
Unterbefehl. Fügen Sie diesem Unterbefehl die Optionen hinzu, indem Sie die Sammlungsinitialisierungssyntax anstelle derOptions
Eigenschaft verwenden, und fügen Sie den Unterbefehl zum Stammbefehl hinzu.Command readCommand = new("read", "Read and display the file.") { fileOption, delayOption, fgcolorOption, lightModeOption }; rootCommand.Subcommands.Add(readCommand);
Ersetzen Sie den
SetAction
Code durch den folgendenSetAction
Code für den neuen Unterbefehl:readCommand.SetAction(parseResult => ReadFile( parseResult.GetValue(fileOption), parseResult.GetValue(delayOption), parseResult.GetValue(fgcolorOption), parseResult.GetValue(lightModeOption)));
Sie rufen den Hauptbefehl
SetAction
nicht mehr auf, da der Hauptbefehl keine Aktion mehr erfordert. Wenn ein Befehl Unterbefehle aufweist, müssen Sie in der Regel einen der Unterbefehle angeben, wenn Sie eine Befehlszeilen-App aufrufen.Ersetzen Sie die
ReadFile
Aktionsmethode durch den folgenden Code:internal static void ReadFile(FileInfo file, int delay, ConsoleColor fgColor, bool lightMode) { Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black; Console.ForegroundColor = fgColor; foreach (string line in File.ReadLines(file.FullName)) { Console.WriteLine(line); Thread.Sleep(TimeSpan.FromMilliseconds(delay * line.Length)); } }
Die App sieht nun wie folgt aus:
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."
};
Option<int> delayOption = new("--delay")
{
Description = "Delay between lines, specified as milliseconds per character in a line.",
DefaultValueFactory = parseResult => 42
};
Option<ConsoleColor> fgcolorOption = new("--fgcolor")
{
Description = "Foreground color of text displayed on the console.",
DefaultValueFactory = parseResult => ConsoleColor.White
};
Option<bool> lightModeOption = new("--light-mode")
{
Description = "Background color of text displayed on the console: default is black, light mode is white."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
Command readCommand = new("read", "Read and display the file.")
{
fileOption,
delayOption,
fgcolorOption,
lightModeOption
};
rootCommand.Subcommands.Add(readCommand);
readCommand.SetAction(parseResult => ReadFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(delayOption),
parseResult.GetValue(fgcolorOption),
parseResult.GetValue(lightModeOption)));
return rootCommand.Parse(args).Invoke();
}
internal static void ReadFile(FileInfo file, int delay, ConsoleColor fgColor, bool lightMode)
{
Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = fgColor;
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
Thread.Sleep(TimeSpan.FromMilliseconds(delay * line.Length));
}
}
}
Testen des neuen Unterbefehls
Wenn Sie nun versuchen, die App auszuführen, ohne den Unterbefehl anzugeben, wird eine Fehlermeldung gefolgt von einer Hilfemeldung angezeigt, die den verfügbaren Unterbefehl angibt.
scl --file sampleQuotes.txt
'--file' was not matched. Did you mean one of the following?
--help
Required command was not provided.
Unrecognized command or argument '--file'.
Unrecognized command or argument 'sampleQuotes.txt'.
Description:
Sample app for System.CommandLine
Usage:
scl [command] [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
Commands:
read Read and display the file.
Der Hilfetext für den Unterbefehl read
zeigt, dass vier Optionen verfügbar sind. Es werden gültige Werte für die Enumeration angezeigt.
scl read -h
Description:
Read and display the file.
Usage:
scl read [options]
Options:
--file <file> The file to read and display on the console.
--delay <delay> Delay between lines, specified as milliseconds per
character in a line. [default: 42]
--fgcolor Foreground color of text displayed on the console.
<Black|Blue|Cyan|DarkBlue|DarkCyan|DarkGray|DarkGreen|Dark [default: White]
Magenta|DarkRed|DarkYellow|Gray|Green|Magenta|Red|White|Ye
llow>
--light-mode Background color of text displayed on the console:
default is black, light mode is white.
-?, -h, --help Show help and usage information
Führen Sie den Unterbefehl read
aus, der nur die --file
Option angibt, und Sie erhalten die Standardwerte für die anderen drei Optionen.
scl read --file sampleQuotes.txt
Die Standardverzögerung von 42 Millisekunden pro Zeichen verursacht eine langsame Lesegeschwindigkeit. Sie können dies beschleunigen, indem Sie eine niedrigere Zahl festlegen --delay
.
scl read --file sampleQuotes.txt --delay 0
Sie können --fgcolor
und --light-mode
verwenden, um Textfarben festzulegen.
scl read --file sampleQuotes.txt --fgcolor red --light-mode
Geben Sie einen ungültigen Wert ein --delay
, und Sie erhalten eine Fehlermeldung:
scl read --file sampleQuotes.txt --delay forty-two
Cannot parse argument 'forty-two' for option '--int' as expected type 'System.Int32'.
Geben Sie einen ungültigen Wert ein --file
, und Sie erhalten eine Ausnahme:
scl read --file nofile
Unhandled exception: System.IO.FileNotFoundException: Could not find file 'C:\bin\Debug\net9.0\nofile''.
File name: 'C:\bin\Debug\net9.0\nofile''
Hinzufügen von Unterbefehlen und benutzerdefinierter Überprüfung
In diesem Abschnitt wird die endgültige Version der App erstellt. Nach Abschluss des Vorgangs verfügt die App über die folgenden Befehle und Optionen:
- Stammbefehl mit einer rekursiven* Option namens
--file
quotes
Befehlread
Befehl mit optionen mit dem Namen--delay
,--fgcolor
, und--light-mode
add
Befehl mit benanntenquote
Argumenten undbyline
delete
Befehl mit dem Namen der Option--search-terms
* Eine rekursive Option ist für den Befehl verfügbar, dem sie zugewiesen ist, und rekursiv für alle seine Unterbefehle.
Hier sehen Sie eine Beispiel-Befehlszeileneingabe, die jeden der verfügbaren Befehle mit den zugehörigen Optionen und Argumenten aufruft:
scl quotes read --file sampleQuotes.txt --delay 40 --fgcolor red --light-mode
scl quotes add "Hello world!" "Nancy Davolio"
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
Ersetzen Sie in Program.cs den Code, der die
--file
Option erstellt, durch den folgenden Code:Option<FileInfo> fileOption = new("--file") { Description = "An option whose argument is parsed as a FileInfo", Required = true, DefaultValueFactory = result => { if (result.Tokens.Count == 0) { return new FileInfo("sampleQuotes.txt"); } string filePath = result.Tokens.Single().Value; if (!File.Exists(filePath)) { result.AddError("File does not exist"); return null; } else { return new FileInfo(filePath); } } };
Dieser Code verwendet
System.CommandLine.Parsing.ArgumentResult
, um benutzerdefinierte Analyse, Überprüfung und Fehlerbehandlung bereitzustellen.Ohne diesen Code werden fehlende Dateien mit einer Ausnahme und Stapelüberwachung gemeldet. Mit diesem Code wird nur die angegebene Fehlermeldung angezeigt.
Dieser Code gibt auch einen Standardwert an, weshalb er
DefaultValueFactory
auf eine benutzerdefinierte Analysemethode setzt.Fügen Sie nach dem Code, der
lightModeOption
erstellt, Optionen und Argumente für dieadd
unddelete
Befehle hinzu.Option<string[]> searchTermsOption = new("--search-terms") { Description = "Strings to search for when deleting entries.", Required = true, AllowMultipleArgumentsPerToken = true }; Argument<string> quoteArgument = new("quote") { Description = "Text of quote." }; Argument<string> bylineArgument = new("byline") { Description = "Byline of quote." };
Mit der
xref:System.CommandLine.Option.AllowMultipleArgumentsPerToken
Einstellung können Sie den--search-terms
Optionsnamen weglassen, wenn Sie Elemente in der Liste nach dem ersten angeben. Die folgenden Beispiele für die Befehlszeileneingabe sind gleichwertig:scl quotes delete --search-terms David "You can do" scl quotes delete --search-terms David --search-terms "You can do"
Ersetzen Sie den Code, der den Stammbefehl und den
read
Befehl erstellt, durch den folgenden Code:RootCommand rootCommand = new("Sample app for System.CommandLine"); fileOption.Recursive = true; rootCommand.Options.Add(fileOption); Command quotesCommand = new("quotes", "Work with a file that contains quotes."); rootCommand.Subcommands.Add(quotesCommand); Command readCommand = new("read", "Read and display the file.") { delayOption, fgcolorOption, lightModeOption }; quotesCommand.Subcommands.Add(readCommand); Command deleteCommand = new("delete", "Delete lines from the file."); deleteCommand.Options.Add(searchTermsOption); quotesCommand.Subcommands.Add(deleteCommand); Command addCommand = new("add", "Add an entry to the file."); addCommand.Arguments.Add(quoteArgument); addCommand.Arguments.Add(bylineArgument); addCommand.Aliases.Add("insert"); quotesCommand.Subcommands.Add(addCommand);
Dieser Code nimmt die folgenden Änderungen vor:
Entfernt die
--file
Option aus demread
Befehl.Fügt die
--file
Option als rekursive Option zum Stammbefehl hinzu.Erstellt einen
quotes
Befehl und fügt ihn dem Stammbefehl hinzu.Fügt den
read
Befehl demquotes
Befehl anstelle des Stammbefehls hinzu.Erstellt
add
unddelete
befehle und fügt sie demquotes
Befehl hinzu.
Das Ergebnis ist die folgende Befehlshierarchie:
- Stammbefehl
quotes
read
add
delete
Die App implementiert jetzt das empfohlene Muster, bei dem der übergeordnete Befehl (
quotes
) einen Bereich oder eine Gruppe angibt und die untergeordneten Elemente (read
,add
,delete
) Aktionen sind.Rekursive Optionen werden auf den Befehl angewendet und rekursiv auf Unterbefehle angewendet. Da sich
--file
im Stammbefehl befindet, wird er automatisch in allen Unterbefehlen der App verfügbar sein.Fügen Sie nach dem
SetAction
Code neuenSetAction
Code für die neuen Unterbefehle hinzu:deleteCommand.SetAction(parseResult => DeleteFromFile( parseResult.GetValue(fileOption), parseResult.GetValue(searchTermsOption))); addCommand.SetAction(parseResult => AddToFile( parseResult.GetValue(fileOption), parseResult.GetValue(quoteArgument), parseResult.GetValue(bylineArgument)) );
Der Unterbefehl
quotes
verfügt nicht über eine Aktion, da es sich nicht um einen Blattbefehl handelt. Unterbefehleread
,add
, unddelete
sind Blattbefehle unterquotes
, undSetAction
wird für jeden von ihnen aufgerufen.Fügen Sie die Aktionen für
add
unddelete
.internal static void DeleteFromFile(FileInfo file, string[] searchTerms) { Console.WriteLine("Deleting from file"); var lines = File.ReadLines(file.FullName).Where(line => searchTerms.All(s => !line.Contains(s))); File.WriteAllLines(file.FullName, lines); } internal static void AddToFile(FileInfo file, string quote, string byline) { Console.WriteLine("Adding to file"); using StreamWriter writer = file.AppendText(); writer.WriteLine($"{Environment.NewLine}{Environment.NewLine}{quote}"); writer.WriteLine($"{Environment.NewLine}-{byline}"); }
Die fertige App sieht wie folgt aus:
using System.CommandLine;
namespace scl;
class Program
{
static int Main(string[] args)
{
Option<FileInfo> fileOption = new("--file")
{
Description = "An option whose argument is parsed as a FileInfo",
Required = true,
DefaultValueFactory = result =>
{
if (result.Tokens.Count == 0)
{
return new FileInfo("sampleQuotes.txt");
}
string filePath = result.Tokens.Single().Value;
if (!File.Exists(filePath))
{
result.AddError("File does not exist");
return null;
}
else
{
return new FileInfo(filePath);
}
}
};
Option<int> delayOption = new("--delay")
{
Description = "Delay between lines, specified as milliseconds per character in a line.",
DefaultValueFactory = parseResult => 42
};
Option<ConsoleColor> fgcolorOption = new("--fgcolor")
{
Description = "Foreground color of text displayed on the console.",
DefaultValueFactory = parseResult => ConsoleColor.White
};
Option<bool> lightModeOption = new("--light-mode")
{
Description = "Background color of text displayed on the console: default is black, light mode is white."
};
Option<string[]> searchTermsOption = new("--search-terms")
{
Description = "Strings to search for when deleting entries.",
Required = true,
AllowMultipleArgumentsPerToken = true
};
Argument<string> quoteArgument = new("quote")
{
Description = "Text of quote."
};
Argument<string> bylineArgument = new("byline")
{
Description = "Byline of quote."
};
RootCommand rootCommand = new("Sample app for System.CommandLine");
fileOption.Recursive = true;
rootCommand.Options.Add(fileOption);
Command quotesCommand = new("quotes", "Work with a file that contains quotes.");
rootCommand.Subcommands.Add(quotesCommand);
Command readCommand = new("read", "Read and display the file.")
{
delayOption,
fgcolorOption,
lightModeOption
};
quotesCommand.Subcommands.Add(readCommand);
Command deleteCommand = new("delete", "Delete lines from the file.");
deleteCommand.Options.Add(searchTermsOption);
quotesCommand.Subcommands.Add(deleteCommand);
Command addCommand = new("add", "Add an entry to the file.");
addCommand.Arguments.Add(quoteArgument);
addCommand.Arguments.Add(bylineArgument);
addCommand.Aliases.Add("insert");
quotesCommand.Subcommands.Add(addCommand);
readCommand.SetAction(parseResult => ReadFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(delayOption),
parseResult.GetValue(fgcolorOption),
parseResult.GetValue(lightModeOption)));
deleteCommand.SetAction(parseResult => DeleteFromFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(searchTermsOption)));
addCommand.SetAction(parseResult => AddToFile(
parseResult.GetValue(fileOption),
parseResult.GetValue(quoteArgument),
parseResult.GetValue(bylineArgument))
);
return rootCommand.Parse(args).Invoke();
}
internal static void ReadFile(FileInfo file, int delay, ConsoleColor fgColor, bool lightMode)
{
Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = fgColor;
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
Thread.Sleep(TimeSpan.FromMilliseconds(delay * line.Length));
}
}
internal static void DeleteFromFile(FileInfo file, string[] searchTerms)
{
Console.WriteLine("Deleting from file");
var lines = File.ReadLines(file.FullName).Where(line => searchTerms.All(s => !line.Contains(s)));
File.WriteAllLines(file.FullName, lines);
}
internal static void AddToFile(FileInfo file, string quote, string byline)
{
Console.WriteLine("Adding to file");
using StreamWriter writer = file.AppendText();
writer.WriteLine($"{Environment.NewLine}{Environment.NewLine}{quote}");
writer.WriteLine($"{Environment.NewLine}-{byline}");
}
}
Erstellen Sie das Projekt, und versuchen Sie dann die folgenden Befehle.
Übermitteln Sie mit dem --file
-Befehl eine nicht vorhandene Datei an read
, und Sie erhalten eine Fehlermeldung anstelle einer Ausnahme und Stapelüberwachung:
scl quotes read --file nofile
File does not exist
Versuchen Sie, den Unterbefehl quotes
auszuführen, und Sie erhalten eine Nachricht, die Sie zur Verwendung von read
, add
oder delete
auffordert.
scl quotes
Required command was not provided.
Description:
Work with a file that contains quotes.
Usage:
scl quotes [command] [options]
Options:
--file <file> An option whose argument is parsed as a FileInfo [default: sampleQuotes.txt]
-?, -h, --help Show help and usage information
Commands:
read Read and display the file.
delete Delete lines from the file.
add, insert <quote> <byline> Add an entry to the file.
Führen Sie den Unterbefehl add
aus, und sehen Sie sich dann das Ende der Textdatei an, um den hinzugefügten Text anzuzeigen:
scl quotes add "Hello world!" "Nancy Davolio"
Führen Sie den Unterbefehl delete
mit Suchzeichenfolgen am Anfang der Datei aus, und sehen Sie sich dann den Anfang der Textdatei an, um zu sehen, wo Text entfernt wurde:
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
Hinweis
Wenn Sie den Ordner "bin/debug/net9.0" ausführen, finden Sie in diesem Ordner die Datei mit Änderungen, die durch die Befehle add
und delete
vorgenommen wurden. Die Kopie der Datei im Projektordner bleibt unverändert.
Nächste Schritte
In diesem Tutorial haben Sie eine einfache Befehlszeilen-App erstellt, die System.CommandLine
verwendet. Weitere Informationen zur Bibliothek finden Sie in System.CommandLine der Übersicht.