Oktatóanyag: Első lépések System.CommandLine
Fontos
System.CommandLine
jelenleg előzetes verzióban érhető el, és ez a dokumentáció a 2.0-s béta 4-es verzióhoz készült.
Egyes információk olyan előzetes termékre vonatkoznak, amely a kiadás előtt lényegesen módosulhat. A Microsoft nem vállal kifejezett vagy törvényi garanciát az itt megjelenő információért.
Ez az oktatóanyag bemutatja, hogyan hozhat létre egy .NET parancssori alkalmazást, amely a System.CommandLine
kódtárat használja. Első lépésként hozzon létre egy egyszerű gyökérparancsot, amely egyetlen lehetőséggel rendelkezik. Ezután hozzáadja ezt a bázist, és létrehoz egy összetettebb alkalmazást, amely több alparancsot és különböző beállításokat tartalmaz az egyes parancsokhoz.
Eben az oktatóanyagban az alábbiakkal fog megismerkedni:
- Parancsok, beállítások és argumentumok létrehozása.
- Adja meg a beállítások alapértelmezett értékeit.
- Beállítások és argumentumok hozzárendelése parancsokhoz.
- Rekurzív módon rendeljen hozzá egy beállítást egy parancs összes alparancsához.
- Többszintű beágyazott alparancsokkal dolgozhat.
- Aliasok létrehozása parancsokhoz és beállításokhoz.
- A ,
string[]
,int
,bool
FileInfo
és enumerálási beállítástípusokkalstring
dolgozhat. - A beállításértékek kötése a parancskezelő kódhoz.
- Egyéni kód használata a beállítások elemzéséhez és érvényesítéséhez.
Előfeltételek
- Egy kódszerkesztő, például a Visual Studio CodeC#-bővítménnyel.
- A .NET 6 SDK.
Vagy
- Visual Studio 2022 , telepített .NET asztali fejlesztési számítási feladattal.
Az alkalmazás létrehozása
Hozzon létre egy "scl" nevű .NET 6-konzolalkalmazás-projektet.
Hozzon létre egy scl nevű mappát a projekthez, majd nyisson meg egy parancssort az új mappában.
Futtassa az alábbi parancsot:
dotnet new console --framework net6.0
Telepítse a(z) System.CommandLine csomagot
Futtassa az alábbi parancsot:
dotnet add package System.CommandLine --prerelease
A
--prerelease
beállításra azért van szükség, mert a kódtár még bétaverzióban van.
Cserélje le a Program.cs fájl tartalmát a következő kódra:
using System.CommandLine; namespace scl; class Program { static async Task<int> Main(string[] args) { var fileOption = new Option<FileInfo?>( name: "--file", description: "The file to read and display on the console."); var rootCommand = new RootCommand("Sample app for System.CommandLine"); rootCommand.AddOption(fileOption); rootCommand.SetHandler((file) => { ReadFile(file!); }, fileOption); return await rootCommand.InvokeAsync(args); } static void ReadFile(FileInfo file) { File.ReadLines(file.FullName).ToList() .ForEach(line => Console.WriteLine(line)); } }
A fenti kód a következőket végzi el:
Létrehoz egy típus FileInfo nevű
--file
beállítást, és hozzárendeli a gyökérparancshoz:var fileOption = new Option<FileInfo?>( name: "--file", description: "The file to read and display on the console."); var rootCommand = new RootCommand("Sample app for System.CommandLine"); rootCommand.AddOption(fileOption);
ReadFile
Ez a metódus lesz meghívva a gyökérparancs meghívásakor:rootCommand.SetHandler((file) => { ReadFile(file!); }, fileOption);
Megjeleníti a megadott fájl tartalmát a gyökérparancs meghívásakor:
static void ReadFile(FileInfo file) { File.ReadLines(file.FullName).ToList() .ForEach(line => Console.WriteLine(line)); }
Az alkalmazás tesztelése
A parancssori alkalmazások fejlesztése során az alábbi módszerek bármelyikét használhatja a teszteléshez:
Futtassa a
dotnet build
parancsot, majd nyisson meg egy parancssort az scl/bin/Debug/net6.0 mappában a végrehajtható fájl futtatásához:dotnet build cd bin/Debug/net6.0 scl --file scl.runtimeconfig.json
Használja
dotnet run
és adja át a beállításértékeket az alkalmazásnak a parancs helyett úgy, hogy beleveszi őket arun
parancsba--
, ahogy az alábbi példában is látható:dotnet run -- --file scl.runtimeconfig.json
A .NET 7.0.100 SDK előzetes verziójában használhatja a
commandLineArgs
launchSettings.json fájlt a parancs futtatásávaldotnet run --launch-profile <profilename>
.Tegye közzé a projektet egy mappában, nyisson meg egy parancssort a mappában, és futtassa a végrehajtható fájlt:
dotnet publish -o publish cd ./publish scl --file scl.runtimeconfig.json
A Visual Studio 2022-ben válassza aHibakeresési tulajdonságokhibakeresése> lehetőséget a menüben, és írja be a beállításokat és argumentumokat a Parancssor argumentumai mezőbe. Például:
Ezután futtassa az alkalmazást például a Ctrl+F5 billentyűkombináció lenyomásával.
Ez az oktatóanyag feltételezi, hogy az első lehetőséget használja.
Az alkalmazás futtatásakor a beállítás által --file
megadott fájl tartalma jelenik meg.
{
"runtimeOptions": {
"tfm": "net6.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "6.0.0"
}
}
}
Súgó kimenete
System.CommandLine
automatikusan biztosítja a súgó kimenetét:
scl --help
Description:
Sample app for System.CommandLine
Usage:
scl [options]
Options:
--file <file> The file to read and display on the console.
--version Show version information
-?, -h, --help Show help and usage information
Verzió kimenete
System.CommandLine
automatikusan biztosítja a verzió kimenetét:
scl --version
1.0.0
Alparancs és beállítások hozzáadása
Ebben a szakaszban:
- Hozzon létre további lehetőségeket.
- Hozzon létre egy alparancsot.
- Rendelje hozzá az új beállításokat az új alparancshoz.
Az új beállításokkal konfigurálhatja az előtér- és háttérszöveg-színeket, valamint az olvasási sebességet. Ezek a funkciók a Teleprompter konzolalkalmazás oktatóanyagából származó idézetek gyűjteményének olvasására szolgálnak.
Másolja a sampleQuotes.txt fájlt a minta GitHub-adattárából a projektkönyvtárba. A fájlok letöltéséről további információt a Minták és oktatóanyagok című témakörben talál.
Nyissa meg a projektfájlt, és adjon hozzá egy
<ItemGroup>
elemet közvetlenül a záró</Project>
címke előtt:<ItemGroup> <Content Include="sampleQuotes.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup>
Ha hozzáadja ezt a korrektúrát, a program az alkalmazás létrehozásakor a bin/debug/net6.0 mappába másolja a szövegfájlt. Így amikor futtatja a végrehajtható fájlt az adott mappában, név szerint érheti el a fájlt mappaelérési út megadása nélkül.
A Program.cs fájlban a beállítást létrehozó
--file
kód után hozzon létre beállításokat az olvasási sebesség és a szövegszínek szabályozásához:var delayOption = new Option<int>( name: "--delay", description: "Delay between lines, specified as milliseconds per character in a line.", getDefaultValue: () => 42); var fgcolorOption = new Option<ConsoleColor>( name: "--fgcolor", description: "Foreground color of text displayed on the console.", getDefaultValue: () => ConsoleColor.White); var lightModeOption = new Option<bool>( name: "--light-mode", description: "Background color of text displayed on the console: default is black, light mode is white.");
A gyökérparancsot létrehozó sor után törölje azt a sort, amely hozzáadja a
--file
lehetőséget. Itt távolítja el, mert hozzáadja egy új alparancshoz.var rootCommand = new RootCommand("Sample app for System.CommandLine"); //rootCommand.AddOption(fileOption);
A gyökérparancsot létrehozó sor után hozzon létre egy
read
alparancsot. Adja hozzá a beállításokat ehhez az alparancshoz, és adja hozzá az alparancsot a gyökérparancshoz.var readCommand = new Command("read", "Read and display the file.") { fileOption, delayOption, fgcolorOption, lightModeOption }; rootCommand.AddCommand(readCommand);
Cserélje le a
SetHandler
kódot az új alparancs következőSetHandler
kódjára:readCommand.SetHandler(async (file, delay, fgcolor, lightMode) => { await ReadFile(file!, delay, fgcolor, lightMode); }, fileOption, delayOption, fgcolorOption, lightModeOption);
A gyökérparancson már nem hív,
SetHandler
mert a gyökérparancsnak már nincs szüksége kezelőre. Ha egy parancshoz alparancsok tartoznak, általában meg kell adnia az alparancsok egyikét egy parancssori alkalmazás meghívásakor.Cserélje le a
ReadFile
kezelőmetódust a következő kódra:internal static async Task ReadFile( FileInfo file, int delay, ConsoleColor fgColor, bool lightMode) { Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black; Console.ForegroundColor = fgColor; List<string> lines = File.ReadLines(file.FullName).ToList(); foreach (string line in lines) { Console.WriteLine(line); await Task.Delay(delay * line.Length); }; }
Az alkalmazás így néz ki:
using System.CommandLine;
namespace scl;
class Program
{
static async Task<int> Main(string[] args)
{
var fileOption = new Option<FileInfo?>(
name: "--file",
description: "The file to read and display on the console.");
var delayOption = new Option<int>(
name: "--delay",
description: "Delay between lines, specified as milliseconds per character in a line.",
getDefaultValue: () => 42);
var fgcolorOption = new Option<ConsoleColor>(
name: "--fgcolor",
description: "Foreground color of text displayed on the console.",
getDefaultValue: () => ConsoleColor.White);
var lightModeOption = new Option<bool>(
name: "--light-mode",
description: "Background color of text displayed on the console: default is black, light mode is white.");
var rootCommand = new RootCommand("Sample app for System.CommandLine");
//rootCommand.AddOption(fileOption);
var readCommand = new Command("read", "Read and display the file.")
{
fileOption,
delayOption,
fgcolorOption,
lightModeOption
};
rootCommand.AddCommand(readCommand);
readCommand.SetHandler(async (file, delay, fgcolor, lightMode) =>
{
await ReadFile(file!, delay, fgcolor, lightMode);
},
fileOption, delayOption, fgcolorOption, lightModeOption);
return rootCommand.InvokeAsync(args).Result;
}
internal static async Task ReadFile(
FileInfo file, int delay, ConsoleColor fgColor, bool lightMode)
{
Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = fgColor;
List<string> lines = File.ReadLines(file.FullName).ToList();
foreach (string line in lines)
{
Console.WriteLine(line);
await Task.Delay(delay * line.Length);
};
}
}
Az új alparancs tesztelése
Most, ha az alparancs megadása nélkül próbálja futtatni az alkalmazást, hibaüzenet jelenik meg, amelyet egy súgóüzenet követ, amely meghatározza az elérhető alparancsot.
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:
--version Show version information
-?, -h, --help Show help and usage information
Commands:
read Read and display the file.
Az alparancs read
súgószövegében látható, hogy négy lehetőség érhető el. Az enumerálás érvényes értékeit jeleníti meg.
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
Futtassa az alparancsot read
, amely csak a --file
beállítást adja meg, és a másik három beállítás alapértelmezett értékeit kapja meg.
scl read --file sampleQuotes.txt
A karakterenkénti alapértelmezett késleltetés 42 ezredmásodpercben lassú olvasási sebességet eredményez. Felgyorsíthatja a sebességet, ha alacsonyabb számot állít be --delay
.
scl read --file sampleQuotes.txt --delay 0
A és --light-mode
a használatával --fgcolor
beállíthatja a szöveg színeit:
scl read --file sampleQuotes.txt --fgcolor red --light-mode
Adjon meg egy érvénytelen értéket, --delay
és hibaüzenet jelenik meg:
scl read --file sampleQuotes.txt --delay forty-two
Cannot parse argument 'forty-two' for option '--int' as expected type 'System.Int32'.
Adjon meg egy érvénytelen értéket, --file
és kivételt kap:
scl read --file nofile
Unhandled exception: System.IO.FileNotFoundException:
Could not find file 'C:\bin\Debug\net6.0\nofile'.
Alparancsok és egyéni érvényesítés hozzáadása
Ez a szakasz az alkalmazás végleges verzióját hozza létre. Ha végzett, az alkalmazás a következő parancsokkal és beállításokkal rendelkezik:
- root parancs egy nevű globális* beállítással
--file
quotes
parancsread
parancsot, amelynek a neve--delay
,--fgcolor
, és--light-mode
add
command with arguments namedquote
andbyline
delete
command with option named--search-terms
* Egy globális beállítás érhető el a parancshoz, amelyhez hozzá van rendelve, és rekurzív módon az összes alparancsa számára.
Íme egy példa parancssori bemenetre, amely meghívja az egyes elérhető parancsokat annak beállításaival és argumentumaival:
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"
A Program.cs fájlban cserélje le a lehetőséget létrehozó
--file
kódot a következő kódra:var fileOption = new Option<FileInfo?>( name: "--file", description: "An option whose argument is parsed as a FileInfo", isDefault: true, parseArgument: result => { if (result.Tokens.Count == 0) { return new FileInfo("sampleQuotes.txt"); } string? filePath = result.Tokens.Single().Value; if (!File.Exists(filePath)) { result.ErrorMessage = "File does not exist"; return null; } else { return new FileInfo(filePath); } });
Ez a kód ParseArgument<T> egyéni elemzést, érvényesítést és hibakezelést biztosít.
A kód nélkül a hiányzó fájlok kivétellel és veremkövetéssel jelennek meg. Ezzel a kóddal csak a megadott hibaüzenet jelenik meg.
Ez a kód egy alapértelmezett értéket is megad, ezért értékre
true
van advaisDefault
. Ha nem értékretrue
van állítvaisDefault
, aparseArgument
delegált nem lesz meghívva, ha nem ad meg bemenetet a számára--file
.A létrehozó
lightModeOption
kód után adja hozzá a és aadd
parancs beállításait ésdelete
argumentumait:var searchTermsOption = new Option<string[]>( name: "--search-terms", description: "Strings to search for when deleting entries.") { IsRequired = true, AllowMultipleArgumentsPerToken = true }; var quoteArgument = new Argument<string>( name: "quote", description: "Text of quote."); var bylineArgument = new Argument<string>( name: "byline", description: "Byline of quote.");
A AllowMultipleArgumentsPerToken beállítással kihagyhatja a
--search-terms
beállítás nevét, amikor az első után elemeket ad meg a listában. A parancssori bevitel megfelelője az alábbi példákat tartalmazza:scl quotes delete --search-terms David "You can do" scl quotes delete --search-terms David --search-terms "You can do"
Cserélje le a gyökérparancsot létrehozó kódot és a
read
parancsot a következő kódra:var rootCommand = new RootCommand("Sample app for System.CommandLine"); rootCommand.AddGlobalOption(fileOption); var quotesCommand = new Command("quotes", "Work with a file that contains quotes."); rootCommand.AddCommand(quotesCommand); var readCommand = new Command("read", "Read and display the file.") { delayOption, fgcolorOption, lightModeOption }; quotesCommand.AddCommand(readCommand); var deleteCommand = new Command("delete", "Delete lines from the file."); deleteCommand.AddOption(searchTermsOption); quotesCommand.AddCommand(deleteCommand); var addCommand = new Command("add", "Add an entry to the file."); addCommand.AddArgument(quoteArgument); addCommand.AddArgument(bylineArgument); addCommand.AddAlias("insert"); quotesCommand.AddCommand(addCommand);
Ez a kód a következő módosításokat hajtja végre:
Eltávolítja a
--file
beállítást aread
parancsból.Globális beállításként adja hozzá a
--file
lehetőséget a gyökérparancshoz.Létrehoz egy
quotes
parancsot, és hozzáadja a gyökérparancshoz.A parancsot
quotes
aread
gyökérparancs helyett a parancshoz adja hozzá.Létrehozza
add
ésdelete
hozzáadja őket aquotes
parancshoz.
Az eredmény a következő parancshierarchia:
- Gyökérparancs
quotes
read
add
delete
Az alkalmazás most implementálja az ajánlott mintát, amelyben a szülőparancs (
quotes
) meghatároz egy területet vagy csoportot, a gyermekparancsai (read
,add
,delete
) pedig műveletek.A rendszer globális beállításokat alkalmaz a parancsra, és rekurzívan az alparancsokra. Mivel
--file
a gyökérparancson van, automatikusan elérhetővé válik az alkalmazás összes alparancsában.SetHandler
A kód után adjon hozzá újSetHandler
kódot az új alparancsokhoz:deleteCommand.SetHandler((file, searchTerms) => { DeleteFromFile(file!, searchTerms); }, fileOption, searchTermsOption); addCommand.SetHandler((file, quote, byline) => { AddToFile(file!, quote, byline); }, fileOption, quoteArgument, bylineArgument);
Az alparancsnak
quotes
nincs kezelője, mert nem levélparancs. Az alparancsok ,add
és a alatt levélparancsokquotes
read
, ésSetHandler
mindegyikhez meghívvadelete
van.Adja hozzá a és
delete
a kezelőitadd
.internal static void DeleteFromFile(FileInfo file, string[] searchTerms) { Console.WriteLine("Deleting from file"); File.WriteAllLines( file.FullName, File.ReadLines(file.FullName) .Where(line => searchTerms.All(s => !line.Contains(s))).ToList()); } 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}"); writer.Flush(); }
A kész alkalmazás a következőképpen néz ki:
using System.CommandLine;
namespace scl;
class Program
{
static async Task<int> Main(string[] args)
{
var fileOption = new Option<FileInfo?>(
name: "--file",
description: "An option whose argument is parsed as a FileInfo",
isDefault: true,
parseArgument: result =>
{
if (result.Tokens.Count == 0)
{
return new FileInfo("sampleQuotes.txt");
}
string? filePath = result.Tokens.Single().Value;
if (!File.Exists(filePath))
{
result.ErrorMessage = "File does not exist";
return null;
}
else
{
return new FileInfo(filePath);
}
});
var delayOption = new Option<int>(
name: "--delay",
description: "Delay between lines, specified as milliseconds per character in a line.",
getDefaultValue: () => 42);
var fgcolorOption = new Option<ConsoleColor>(
name: "--fgcolor",
description: "Foreground color of text displayed on the console.",
getDefaultValue: () => ConsoleColor.White);
var lightModeOption = new Option<bool>(
name: "--light-mode",
description: "Background color of text displayed on the console: default is black, light mode is white.");
var searchTermsOption = new Option<string[]>(
name: "--search-terms",
description: "Strings to search for when deleting entries.")
{ IsRequired = true, AllowMultipleArgumentsPerToken = true };
var quoteArgument = new Argument<string>(
name: "quote",
description: "Text of quote.");
var bylineArgument = new Argument<string>(
name: "byline",
description: "Byline of quote.");
var rootCommand = new RootCommand("Sample app for System.CommandLine");
rootCommand.AddGlobalOption(fileOption);
var quotesCommand = new Command("quotes", "Work with a file that contains quotes.");
rootCommand.AddCommand(quotesCommand);
var readCommand = new Command("read", "Read and display the file.")
{
delayOption,
fgcolorOption,
lightModeOption
};
quotesCommand.AddCommand(readCommand);
var deleteCommand = new Command("delete", "Delete lines from the file.");
deleteCommand.AddOption(searchTermsOption);
quotesCommand.AddCommand(deleteCommand);
var addCommand = new Command("add", "Add an entry to the file.");
addCommand.AddArgument(quoteArgument);
addCommand.AddArgument(bylineArgument);
addCommand.AddAlias("insert");
quotesCommand.AddCommand(addCommand);
readCommand.SetHandler(async (file, delay, fgcolor, lightMode) =>
{
await ReadFile(file!, delay, fgcolor, lightMode);
},
fileOption, delayOption, fgcolorOption, lightModeOption);
deleteCommand.SetHandler((file, searchTerms) =>
{
DeleteFromFile(file!, searchTerms);
},
fileOption, searchTermsOption);
addCommand.SetHandler((file, quote, byline) =>
{
AddToFile(file!, quote, byline);
},
fileOption, quoteArgument, bylineArgument);
return await rootCommand.InvokeAsync(args);
}
internal static async Task ReadFile(
FileInfo file, int delay, ConsoleColor fgColor, bool lightMode)
{
Console.BackgroundColor = lightMode ? ConsoleColor.White : ConsoleColor.Black;
Console.ForegroundColor = fgColor;
var lines = File.ReadLines(file.FullName).ToList();
foreach (string line in lines)
{
Console.WriteLine(line);
await Task.Delay(delay * line.Length);
};
}
internal static void DeleteFromFile(FileInfo file, string[] searchTerms)
{
Console.WriteLine("Deleting from file");
File.WriteAllLines(
file.FullName, File.ReadLines(file.FullName)
.Where(line => searchTerms.All(s => !line.Contains(s))).ToList());
}
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}");
writer.Flush();
}
}
Hozza létre a projektet, majd próbálkozzon az alábbi parancsokkal.
Küldjön be egy nem létező fájlt --file
a read
paranccsal, és hibaüzenet jelenik meg kivétel és veremkövetés helyett:
scl quotes read --file nofile
File does not exist
Próbálja meg futtatni az alparancsot quotes
, és megjelenik egy üzenet, amely arra utasítja, hogy használja read
a , add
vagy delete
a parancsot:
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.
Futtassa az alparancsot add
, majd tekintse meg a szövegfájl végét a hozzáadott szöveg megtekintéséhez:
scl quotes add "Hello world!" "Nancy Davolio"
Futtassa az alparancsot delete
a fájl elejéről származó keresési sztringekkel, majd tekintse meg a szövegfájl elejét a szöveg eltávolításának helyének megtekintéséhez:
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
Megjegyzés
Ha a bin/debug/net6.0 mappában fut, abban a mappában találja a és delete
a add
parancs módosításait tartalmazó fájlt. A projektmappában lévő fájl másolata változatlan marad.
Következő lépések
Ebben az oktatóanyagban létrehozott egy egyszerű parancssori alkalmazást, amely a következőt használja System.CommandLine
: . A kódtárról további információt az áttekintésben találSystem.CommandLine.