Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Deze zelfstudie laat zien hoe u een .NET-opdrachtregel-app maakt die gebruikmaakt van de System.CommandLine bibliotheek. U begint met het maken van een eenvoudige hoofdopdracht met één optie. Vervolgens bouwt u op die basis en maakt u een complexere app met meerdere subopdrachten en verschillende opties voor elke opdracht.
In deze zelfstudie leert u het volgende:
- Opdrachten, opties en argumenten maken.
- Geef standaardwaarden op voor opties.
- Opties en argumenten toewijzen aan opdrachten.
- Wijs een optie recursief toe aan alle subopdrachten onder een opdracht.
- Omgaan met meerdere niveaus van geneste subopdrachten.
- Maak aliassen voor opdrachten en opties.
- Werken met
string,string[],int,bool,FileInfoen enumeratietypen. - Optiewaarden lezen in opdrachtactiecode.
- Gebruik aangepaste code voor het parseren en valideren van opties.
Vereiste voorwaarden
- De nieuwste .NET SDK-
- Visual Studio Code-editor
- De C# DevKit
Of
- Visual Studio 2022 met de .NET-desktopontwikkeling workload geïnstalleerd.
De app maken
Maak een .NET 9-console-app-project met de naam 'scl'.
Maak een map met de naam scl voor het project en open vervolgens een opdrachtprompt in de nieuwe map.
Voer de volgende opdracht uit:
dotnet new console --framework net9.0
Het System.CommandLine-pakket installeren
Voer de volgende opdracht uit:
dotnet add package System.CommandLine --prereleaseOf in .NET 10+:
dotnet package add System.CommandLine --prereleaseDe
--prereleaseoptie is nodig omdat de bibliotheek nog in bèta is.
De argumenten parseren
Vervang de inhoud van Program.cs door de volgende 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.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); } } }
De voorgaande code:
- Hiermee maakt u een optie met de naam
--filevan het type FileInfo en voegt u deze toe aan de hoofdopdracht:
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);
- Parseert de
argsen controleert of er een waarde is opgegeven voor--filede optie. Zo ja, dan roept het de methode aan met behulp van geparseerde waardeReadFileen retourneert0afsluitcode:
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.Errors.Count == 0 && parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
ReadFile(parsedFile);
return 0;
}
- Als er geen waarde is opgegeven voor
--file, worden de beschikbare parseringsfouten afgedrukt en wordt de afsluitcode1geretourneerd.
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
- De
ReadFilemethode leest het opgegeven bestand en geeft de inhoud ervan weer op de console:
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
De app testen
U kunt een van de volgende manieren gebruiken om te testen tijdens het ontwikkelen van een opdrachtregel-app:
Voer de
dotnet buildopdracht uit en open vervolgens een opdrachtprompt in de map scl/bin/Debug/net9.0 om het uitvoerbare bestand uit te voeren:dotnet build cd bin/Debug/net9.0 scl --file scl.runtimeconfig.jsonGebruik
dotnet runen geef optiewaarden door aan de app in plaats van aan derunopdracht door ze op te geven na--, zoals in het volgende voorbeeld:dotnet run -- --file bin/Debug/net9.0/scl.runtimeconfig.json
In deze zelfstudie wordt ervan uitgegaan dat u de eerste van deze opties gebruikt.
Wanneer u de app uitvoert, wordt de inhoud van het bestand weergegeven dat is opgegeven door de --file optie.
{
"runtimeOptions": {
"tfm": "net9.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
}
}
}
Maar wat gebeurt er als je het vraagt om de helpfunctie weer te geven met behulp van --help? Er wordt niets afgedrukt naar de console, omdat de app het scenario waarin --file niet is opgegeven nog niet wordt verwerkt en er geen parseringsfouten zijn.
De argumenten parseren en ParseResult aanroepen
System.CommandLine hiermee kunt u een actie opgeven die wordt aangeroepen wanneer een bepaald symbool (opdracht, instructie of optie) wordt geparseerd. De actie is een gemachtigde die een System.CommandLine.ParseResult parameter neemt en een int afsluitcode retourneert (asynchrone acties zijn ook beschikbaar). De afsluitcode wordt geretourneerd door de System.CommandLine.Parsing.ParseResult.Invoke methode en kan worden gebruikt om aan te geven of de opdracht is uitgevoerd of niet.
Vervang de inhoud van Program.cs door de volgende 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); } } }
De voorgaande code:
Hiermee geeft u op dat
ReadFiledit de methode is die wordt aangeroepen wanneer de hoofdopdracht wordt aangeroepen:rootCommand.SetAction(parseResult => { FileInfo parsedFile = parseResult.GetValue(fileOption); ReadFile(parsedFile); return 0; });Parseert het
argsresultaat en roept het resultaat aan :ParseResult parseResult = rootCommand.Parse(args); return parseResult.Invoke();
Wanneer u de app uitvoert, wordt de inhoud van het bestand weergegeven dat is opgegeven door de --file optie.
Wat gebeurt er als u het vraagt om de hulp weer te geven door --help op te geven?
scl --help
De volgende uitvoer wordt weergegeven:
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
RootCommand Biedt standaard de Help-optie, versieoptie en suggestie-instructie. De ParseResult.Invoke(InvocationConfiguration) methode is verantwoordelijk voor het aanroepen van de actie van geparseerd symbool. Dit kan de actie zijn die expliciet is gedefinieerd voor de opdracht of de Help-actie die is gedefinieerd voor System.CommandLineSystem.CommandLine.Help.HelpOption. Bovendien worden, wanneer eventuele parseringsfouten worden gedetecteerd, deze afgedrukt naar de standaardfout, wordt de standaarduitvoer afgedrukt en wordt deze geretourneerd 1 als de afsluitcode:
scl --invalid bla
Unrecognized command or argument '--invalid'.
Unrecognized command or argument 'bla'.
Een subopdracht en opties toevoegen
In deze sectie gaat u het volgende doen:
- Maak meer opties.
- Maak een subopdracht.
- Wijs de nieuwe opties toe aan de nieuwe subopdracht.
Met de nieuwe opties kunt u de voorgrond- en achtergrondtekstkleuren en de leessnelheid configureren. Deze functies worden gebruikt om een verzameling citaten te lezen die afkomstig zijn uit de handleiding van de Teleprompter-console-app.
Kopieer het sampleQuotes.txt bestand uit de GitHub-opslagplaats voor dit voorbeeld naar uw projectmap. Zie de instructies in Voorbeelden en zelfstudies voor meer informatie over het downloaden van bestanden.
Open het projectbestand en voeg een
<ItemGroup>element toe vlak voor de afsluitende</Project>tag:<ItemGroup> <Content Include="sampleQuotes.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup>Als u deze markering toevoegt, wordt het tekstbestand gekopieerd naar de map bin/debug/net9.0 wanneer u de app bouwt. Dus wanneer u het uitvoerbare bestand in die map uitvoert, kunt u het bestand op naam openen zonder een mappad op te geven.
Maak in Program.cs, na de code die de
--fileoptie maakt, opties om de leessnelheid en tekstkleuren te beheren: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." };Verwijder na de regel die de hoofdopdracht maakt de code waarmee de
--fileoptie wordt toegevoegd. U verwijdert deze hier omdat u deze toevoegt aan een nieuwe subopdracht.Maak na de regel die de hoofdopdracht maakt een
readsubopdracht. Voeg de opties toe aan deze subopdracht (met behulp van de syntaxis van de initialisatiefunctie voor verzamelingen in plaatsOptionsvan eigenschap) en voeg de subopdracht toe aan de hoofdopdracht.Command readCommand = new("read", "Read and display the file.") { fileOption, delayOption, fgcolorOption, lightModeOption }; rootCommand.Subcommands.Add(readCommand);Vervang de
SetActioncode door de volgendeSetActioncode voor de nieuwe subopdracht:readCommand.SetAction(parseResult => ReadFile( parseResult.GetValue(fileOption), parseResult.GetValue(delayOption), parseResult.GetValue(fgcolorOption), parseResult.GetValue(lightModeOption)));U roept niet langer
SetActionaan op de root-opdracht omdat de root-opdracht geen actie meer vereist. Wanneer een opdracht subopdrachten bevat, moet u doorgaans een van de subopdrachten opgeven bij het aanroepen van een opdrachtregel-app.Vervang de
ReadFileactiemethode door de volgende 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)); } }
De app ziet er nu als volgt uit:
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));
}
}
}
De nieuwe subopdracht testen
Als u de app probeert uit te voeren zonder de subopdracht op te geven, wordt er een foutbericht weergegeven, gevolgd door een Help-bericht waarin de subopdracht wordt opgegeven die beschikbaar is.
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.
In de Help-tekst voor subopdracht read ziet u dat er vier opties beschikbaar zijn. Er worden geldige waarden voor de opsomming weergegeven.
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
Voer een subopdracht read uit die alleen de --file optie opgeeft en u krijgt de standaardwaarden voor de andere drie opties.
scl read --file sampleQuotes.txt
De standaardvertraging van 42 milliseconden per teken zorgt voor een trage leessnelheid. U kunt dit versnellen door een lager getal in te stellen --delay .
scl read --file sampleQuotes.txt --delay 0
U kunt --fgcolor en --light-mode gebruiken om tekstkleuren in te stellen.
scl read --file sampleQuotes.txt --fgcolor red --light-mode
Geef een ongeldige waarde op voor --delay en u krijgt een foutbericht:
scl read --file sampleQuotes.txt --delay forty-two
Cannot parse argument 'forty-two' for option '--int' as expected type 'System.Int32'.
Geef een ongeldige waarde op voor --file en u krijgt een uitzondering:
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''
Subopdrachten en aangepaste validatie toevoegen
In deze sectie wordt de definitieve versie van de app gemaakt. Wanneer u klaar bent, beschikt de app over de volgende opdrachten en opties:
- hoofdopdracht met een recursieve* optie met de naam
--file-
quotesbevelen-
readopdracht met opties met de naam--delay,--fgcoloren--light-mode -
addopdracht met argumenten met de naamquoteenbyline -
deleteopdracht met optie met de naam--search-terms
-
-
* Er is een recursieve optie beschikbaar voor de opdracht waaraan deze is toegewezen en recursief aan alle bijbehorende subopdrachten.
Hier ziet u voorbeeld van opdrachtregelinvoer die elk van de beschikbare opdrachten aanroept met de bijbehorende opties en argumenten:
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"
Vervang in Program.cs de code waarmee de
--fileoptie wordt gemaakt door de volgende 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); } } };Deze code maakt gebruik
System.CommandLine.Parsing.ArgumentResultvan aangepaste parsering, validatie en foutafhandeling.Zonder deze code worden ontbrekende bestanden met een uitzondering en stack trace gerapporteerd. Met deze code wordt alleen het opgegeven foutbericht weergegeven.
Deze code specificeert ook een standaardwaarde, wat de reden is dat
DefaultValueFactorywordt ingesteld op een aangepaste parseringsmethode.Voeg na de code die
lightModeOptioncreëert, opties en argumenten toe voor deaddendeletecommando's.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." };Met
xref:System.CommandLine.Option.AllowMultipleArgumentsPerTokende instelling kunt u de--search-termsoptienaam weglaten bij het opgeven van elementen in de lijst na de eerste. Dit maakt de volgende voorbeelden van opdrachtregelinvoerequivalent:scl quotes delete --search-terms David "You can do" scl quotes delete --search-terms David --search-terms "You can do"Vervang de code waarmee de hoofdopdracht en de
readopdracht worden gemaakt door de volgende 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);Met deze code worden de volgende wijzigingen aangebracht:
Hiermee verwijdert u de
--fileoptie uit dereadopdracht.Hiermee voegt u de
--fileoptie toe als recursieve optie aan de hoofdopdracht.Hiermee maakt u een
quotesopdracht en voegt u deze toe aan de hoofdopdracht.Hiermee voegt u de
readopdracht toe aan dequotesopdracht in plaats van aan de hoofdopdracht.Hiermee maakt
addendeleteopdrachten en voegt ze toe aan dequotesopdracht.
Het resultaat is de volgende opdrachthiërarchie:
- Hoofdopdracht
quotesreadadddelete
De app implementeert nu het aanbevolen patroon waarbij de bovenliggende opdracht (
quotes) een gebied of groep opgeeft en de onderliggende opdrachten (read,add,delete) acties zijn.Recursieve opties worden toegepast op de opdracht en recursief op subopdrachten. Omdat
--filedeze zich in de hoofdopdracht bevindt, is deze automatisch beschikbaar in alle subopdrachten van de app.Voeg na de
SetActioncode nieuweSetActioncode toe voor de nieuwe subopdrachten:deleteCommand.SetAction(parseResult => DeleteFromFile( parseResult.GetValue(fileOption), parseResult.GetValue(searchTermsOption))); addCommand.SetAction(parseResult => AddToFile( parseResult.GetValue(fileOption), parseResult.GetValue(quoteArgument), parseResult.GetValue(bylineArgument)) );Subopdracht
quotesheeft geen actie omdat het geen leaf-opdracht is. Subopdrachtenread,addendeletezijn leaf-opdrachten onderquotes, enSetActionworden aangeroepen voor elk van deze opdrachten.Voeg de acties voor
addendelete.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}"); }
De voltooide app ziet er als volgt uit:
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}");
}
}
Bouw het project, en voer daarna de volgende opdrachten uit.
Verzend een niet-bestaand bestand naar --file met de read opdracht en u krijgt een foutmelding in plaats van een exceptie en stack-trace:
scl quotes read --file nofile
File does not exist
Probeer de subopdracht quotes uit te voeren en u krijgt een bericht waarin u wordt verwezen naar het gebruik van read, add, of delete.
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.
Voer de subopdracht adduit en kijk vervolgens naar het einde van het tekstbestand om de toegevoegde tekst weer te geven:
scl quotes add "Hello world!" "Nancy Davolio"
Voer een subopdracht delete uit met zoekreeksen vanaf het begin van het bestand en kijk vervolgens naar het begin van het tekstbestand om te zien waar tekst is verwijderd:
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
Notitie
Als u in de de map bin/debug/net9.0 werkt, vindt u het bestand met wijzigingen van de add en delete opdrachten. De kopie van het bestand in de projectmap blijft ongewijzigd.
Volgende stappen
In deze zelfstudie hebt u een eenvoudige opdrachtregel-app gemaakt die gebruikmaakt van System.CommandLine. Zie System.CommandLine het overzicht voor meer informatie over de bibliotheek.