Dela via


Självstudie: Kom igång med System.CommandLine

Viktigt!

System.CommandLine är för närvarande i förhandsversion. Den här dokumentationen gäller version 2.0 beta 7. Viss information gäller förhandsversionsprodukt som kan ändras avsevärt innan den släpps. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

Den här självstudien visar hur du skapar en .NET-kommandoradsapp som använder System.CommandLine-biblioteket. Du börjar med att skapa ett enkelt rotkommando som har ett alternativ. Sedan skapar du en mer komplex app som innehåller flera underkommandon och olika alternativ för varje kommando.

I den här handledningen kommer du lära dig att:

  • Skapa kommandon, alternativ och argument.
  • Ange standardvärden för alternativ.
  • Tilldela alternativ och argument till kommandon.
  • Tilldela ett alternativ rekursivt till alla underkommandon under ett kommando.
  • Arbeta med flera nivåer av kapslade underkommandon.
  • Skapa alias för kommandon och alternativ.
  • Arbeta med string, string[], int, bool, FileInfo och alternativtyper.
  • Läs alternativvärden i kommandoåtgärdskoden.
  • Använd anpassad kod för att parsa och verifiera alternativ.

Förutsättningar

Eller

Skapa appen

Skapa ett .NET 9-konsolappprojekt med namnet "scl".

  1. Skapa en mapp med namnet scl för projektet och öppna sedan en kommandotolk i den nya mappen.

  2. Kör följande kommando:

    dotnet new console --framework net9.0
    

Installera System.CommandLine-paketet

  • Kör följande kommando:

    dotnet add package System.CommandLine --prerelease
    

    Eller i .NET 10+:

    dotnet package add System.CommandLine --prerelease
    

    Det --prerelease alternativet är nödvändigt eftersom biblioteket fortfarande är i betaversion.

Analysera argumenten

  1. Ersätt innehållet i Program.cs med följande kod:

    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);
            }
        }
    }
    

Föregående kod:

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);
  • Parsar args och kontrollerar om något värde har angetts för --file alternativet. I så fall anropas ReadFile metoden med parsat värde och returnerar 0 slutkod:
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.Errors.Count == 0 && parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
    ReadFile(parsedFile);
    return 0;
}
  • Om inget värde angavs för --fileskriver det ut tillgängliga parsningsfel och returnerar 1 slutkod:
foreach (ParseError parseError in parseResult.Errors)
{
    Console.Error.WriteLine(parseError.Message);
}
return 1;
  • Metoden ReadFile läser den angivna filen och visar dess innehåll i konsolen:
static void ReadFile(FileInfo file)
{
    foreach (string line in File.ReadLines(file.FullName))
    {
        Console.WriteLine(line);
    }
}

Testa appen

Du kan använda något av följande sätt att testa när du utvecklar en kommandoradsapp:

  • dotnet build Kör kommandot och öppna sedan en kommandotolk i mappen scl/bin/Debug/net9.0 för att köra den körbara filen:

    dotnet build
    cd bin/Debug/net9.0
    scl --file scl.runtimeconfig.json
    
  • Använd dotnet run och skicka alternativvärden till appen i stället för till kommandot run genom att inkludera dem efter --, som i följande exempel:

    dotnet run -- --file bin/Debug/net9.0/scl.runtimeconfig.json
    

Den här handledningen förutsätter att du använder det första av dessa alternativ.

När du kör appen visas innehållet i filen som anges av alternativet --file.

{
  "runtimeOptions": {
    "tfm": "net9.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "9.0.0"
    }
  }
}

Men vad händer om du ber den att visa hjälpen genom att tillhandahålla --help? Ingenting skrivs ut till konsolen eftersom appen ännu inte hanterar scenariot där --file inte tillhandahålls och det inte finns några parsfel.

Parsa argumenten och anropa ParseResult

System.CommandLine gör att du kan ange en åtgärd som anropas när en viss symbol (kommando, direktiv eller alternativ) parsas korrekt. Åtgärden är ett ombud som tar en System.CommandLine.ParseResult parameter och returnerar en int slutkod (asynkrona åtgärder är också tillgängliga). Slutkoden returneras av System.CommandLine.Parsing.ParseResult.Invoke metoden och kan användas för att ange om kommandot kördes korrekt eller inte.

  1. Ersätt innehållet i Program.cs med följande kod:

    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);
            }
        }
    }
    

Föregående kod:

  • Anger att ReadFile är den metod som anropas när rotkommandot anropas:

    rootCommand.SetAction(parseResult =>
    {
        FileInfo parsedFile = parseResult.GetValue(fileOption);
        ReadFile(parsedFile);
        return 0;
    });
    
  • Parsar args och anropar resultatet:

    ParseResult parseResult = rootCommand.Parse(args);
    return parseResult.Invoke();
    

När du kör appen visas innehållet i filen som anges av alternativet --file.

Vad händer om du ber den att visa hjälpen genom att ange --help?

scl --help

Följande utdata skrivs ut:

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 Som standard finns hjälpalternativ, versionsalternativ och förslagsdirektiv. Metoden ParseResult.Invoke(InvocationConfiguration) ansvarar för att anropa åtgärden för parsad symbol. Det kan vara den åtgärd som uttryckligen definierats för kommandot eller den hjälpåtgärd som definieras av System.CommandLine för System.CommandLine.Help.HelpOption. När den identifierar eventuella parsningsfel skriver den dessutom ut dem till standardfelet, skriver ut hjälp med standardutdata och returnerar 1 som slutkod:

scl --invalid bla
Unrecognized command or argument '--invalid'.
Unrecognized command or argument 'bla'.

Lägg till en underkommando och alternativ

I det här avsnittet ska du:

  • Skapa fler alternativ.
  • Skapa en underkommando.
  • Tilldela de nya alternativen till ett nytt underkommando.

Med de nya alternativen kan du konfigurera förgrunds- och bakgrundstextfärgerna och avläsningshastigheten. De här funktionerna kommer att användas för att läsa en samling citat som kommer från Teleprompter-konsolappens självstudie.

  1. Kopiera sampleQuotes.txt-filen från GitHub-lagringsplatsen för det här exemplet till projektkatalogen. Information om hur du laddar ned filer finns i anvisningarna i Exempel och självstudier.

  2. Öppna projektfilen och lägg till ett <ItemGroup>-element precis före den avslutande </Project>-taggen:

    <ItemGroup>
      <Content Include="sampleQuotes.txt">
        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </Content>
    </ItemGroup>
    

    Om du lägger till den här markeringen kopieras textfilen till mappen bin/debug/net9.0 när du skapar appen. Så när du kör den körbara filen i mappen kan du komma åt filen med hjälp av namn utan att ange en mappsökväg.

  3. I Program.cs, efter koden som skapar alternativet --file, skapar du alternativ för att styra avläsningshastigheten och textfärgerna:

    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."
    };
    
  4. Efter raden som skapar rotkommandot tar du bort koden som lägger --file till alternativet i det. Du tar bort den här eftersom du lägger till den i ett nytt delkommando.

  5. Efter raden som skapar rotkommandot skapar du en read underkommando. Lägg till alternativen i den här underkommandot (med hjälp av insamlingsinitieringssyntaxen i stället Options för egenskapen) och lägg till underkommandot i rotkommandot.

    Command readCommand = new("read", "Read and display the file.")
    {
        fileOption,
        delayOption,
        fgcolorOption,
        lightModeOption
    };
    rootCommand.Subcommands.Add(readCommand);
    
  6. Ersätt SetAction-koden med följande SetAction kod för den nya underkommandot:

    readCommand.SetAction(parseResult => ReadFile(
        parseResult.GetValue(fileOption),
        parseResult.GetValue(delayOption),
        parseResult.GetValue(fgcolorOption),
        parseResult.GetValue(lightModeOption)));
    

    Du anropar SetAction inte längre rotkommandot eftersom rotkommandot inte längre behöver en åtgärd. När ett kommando har underkommandon måste du vanligtvis ange en av underkommandona när du anropar en kommandoradsapp.

  7. ReadFile Ersätt åtgärdsmetoden med följande kod:

    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));
        }
    }
    

Appen ser nu ut så här:

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));
        }
    }
}

Testa den nya underkommandot

Om du nu försöker köra appen utan att ange underkommandot får du ett felmeddelande följt av ett hjälpmeddelande som anger den underkommando som är tillgänglig.

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.

Hjälptexten för underkommandon read visar att fyra alternativ är tillgängliga. Den visar giltiga värden för enum.

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

Kör underkommandot read anger endast alternativet --file och du får standardvärdena för de andra tre alternativen.

scl read --file sampleQuotes.txt

Standardfördröjningen på 42 millisekunder per tecken orsakar en långsam avläsningshastighet. Du kan påskynda det genom att ange --delay till ett lägre tal.

scl read --file sampleQuotes.txt --delay 0

Du kan använda --fgcolor och --light-mode för att ange textfärger:

scl read --file sampleQuotes.txt --fgcolor red --light-mode

Ange ett ogiltigt värde för --delay och du får ett felmeddelande:

scl read --file sampleQuotes.txt --delay forty-two
Cannot parse argument 'forty-two' for option '--int' as expected type 'System.Int32'.

Ange ett ogiltigt värde för --file och du får ett undantag:

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''

Lägga till underkommandon och anpassad validering

Det här avsnittet skapar den slutliga versionen av appen. När appen är klar har den följande kommandon och alternativ:

  • rotkommando med ett rekursivt* alternativ med namnet --file
    • quotes kommando
      • read-kommandot med alternativen --delay, --fgcoloroch --light-mode
      • add kommando med argument med namnet quote och byline
      • delete kommando med alternativet med namnet --search-terms

* Ett rekursivt alternativ är tillgängligt för kommandot som det tilldelas till och rekursivt till alla dess underkommandon.

Här är exempel på kommandoradsindata som anropar vart och ett av de tillgängliga kommandona med dess alternativ och argument:

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"
  1. I Program.csersätter du koden som skapar alternativet --file med följande kod:

    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);
            }
        }
    };
    

    Den här koden använder System.CommandLine.Parsing.ArgumentResult för att tillhandahålla anpassad parsning, validering och felhantering.

    Utan den här koden rapporteras saknade filer med ett undantag och stackspårning. Med den här koden visas bara det angivna felmeddelandet.

    Den här koden anger också ett standardvärde, vilket är anledningen till att den ställer in DefaultValueFactory till en anpassad parsningsmetod.

  2. Efter koden som skapar lightModeOptionlägger du till alternativ och argument för kommandona add och delete:

    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."
    };
    

    Med inställningen xref:System.CommandLine.Option.AllowMultipleArgumentsPerToken kan du utelämna namnet på --search-terms när du specificerar element i listan efter det första elementet. Det gör följande exempel på kommandoradsindata likvärdiga:

    scl quotes delete --search-terms David "You can do"
    scl quotes delete --search-terms David --search-terms "You can do"
    
  3. Ersätt koden som skapar rotkommandot och kommandot read med följande kod:

    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);
    

    Den här koden gör följande ändringar:

    • Tar bort alternativet --file från kommandot read.

    • Lägger till alternativet --file som ett rekursivt alternativ i rotkommandot.

    • Skapar ett quotes kommando och lägger till det i rotkommandot.

    • Lägger till kommandot read i kommandot quotes i stället för till rotkommandot.

    • Skapar kommandon för add och delete och lägger till dem i kommandot quotes.

    Resultatet är följande kommandohierarki:

    • Rotkommando
      • quotes
        • read
        • add
        • delete

    Appen implementerar nu det rekommenderade mönstret där det överordnade kommandot (quotes) anger ett område eller en grupp, och dess underordnade kommandon (read, add, delete) är åtgärder.

    Rekursiva alternativ tillämpas på kommandot och rekursivt på underkommandon. Eftersom --file finns i rotkommandot blir det automatiskt tillgängligt i alla underkommandon i appen.

  4. Efter SetAction-koden, lägg till nya SetAction-koden för de nya underkommandona:

    deleteCommand.SetAction(parseResult => DeleteFromFile(
        parseResult.GetValue(fileOption),
        parseResult.GetValue(searchTermsOption)));
    
    addCommand.SetAction(parseResult => AddToFile(
        parseResult.GetValue(fileOption),
        parseResult.GetValue(quoteArgument),
        parseResult.GetValue(bylineArgument))
        );
    

    Underkommandot quotes har ingen åtgärd eftersom det inte är ett lövkommando. Underkommandon read, addoch delete är lövkommandon under quotesoch SetAction anropas för var och en av dem.

  5. Lägg till åtgärderna för add och delete.

    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}");
    }
    

Den färdiga appen ser ut så här:

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}");
    }
}

Skapa projektet och prova sedan följande kommandon.

Skicka en obefintlig fil till --file med kommandot read och du får ett felmeddelande i stället för ett undantag och stackspårning:

scl quotes read --file nofile
File does not exist

Försök att köra underkommandot quotes och du får ett meddelande som uppmanar dig att använda read, addeller 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.

Kör underkommandot addoch titta sedan på slutet av textfilen för att se den tillagda texten:

scl quotes add "Hello world!" "Nancy Davolio"

Kör underkommandot delete med söksträngar från början av filen och titta sedan på början av textfilen för att se var texten har tagits bort:

scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"

Anmärkning

Om du kör mappen bin/debug/net9.0 hittar du filen med ändringar från add kommandona och delete i mappen bin/debug/net9.0. Kopian av filen i projektmappen förblir oförändrad.

Nästa steg

I den här självstudien skapade du en enkel kommandoradsapp som använder System.CommandLine. Mer information om biblioteket finns i System.CommandLine översikt.