Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это важно
System.CommandLine
в настоящее время находится в предварительной версии, и эта документация предназначена для версии 2.0 бета-версии 5.
Некоторые сведения относятся к предварительному выпуску продукта, который может быть существенно изменен до его выпуска. Корпорация Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых в отношении информации, предоставленной здесь.
В этом руководстве показано, как создать приложение командной строки .NET, использующее библиотеку System.CommandLine
. Сначала вы создадите простую корневую команду, которая имеет один вариант. Затем вы создадите более сложное приложение, содержащее несколько вложенных команд и различные параметры для каждой команды.
В этом руководстве описано, как:
- Создание команд, параметров и аргументов.
- Укажите значения по умолчанию для параметров.
- Назначение параметров и аргументов командам.
- Назначьте опцию рекурсивно всем подкомандам под командой.
- Работа с несколькими уровнями вложенных подкоманд.
- Создайте псевдонимы для команд и параметров.
- Работа с типами
string
,string[]
,int
,bool
,FileInfo
и перечисления. - Чтение значений опций в коде выполнения команды.
- Используйте пользовательский код для анализа и проверки параметров.
Предпосылки
- Последняя версия .NET SDK
- Visual Studio Code редактор
- C# DevKit
Или
- Visual Studio 2022 с установленным компонентом разработки десктопных приложений .NET.
Создание приложения
Создайте проект консольного приложения .NET 9 с именем SCL.
Создайте папку с именем scl для проекта, а затем откройте командную строку в новой папке.
Выполните следующую команду:
dotnet new console --framework net9.0
Установка пакета System.CommandLine
Выполните следующую команду:
dotnet add package System.CommandLine --prerelease
Или в .NET 10+:
dotnet package add System.CommandLine --prerelease
Параметр
--prerelease
необходим, так как библиотека по-прежнему находится в бета-версии.
Анализ аргументов
Замените содержимое файла Program.cs кодом, приведенным ниже.
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); } } }
Предыдущий код:
- Создает параметр с именем
--file
типа FileInfo и добавляет его в корневую команду:
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);
- Анализирует
args
, и проверяет, было ли указано какое-либо значение для параметра--file
. В этом случае вызывается методReadFile
, используя разобранное значение, и возвращает код выхода0
.
ParseResult parseResult = rootCommand.Parse(args);
if (parseResult.GetValue(fileOption) is FileInfo parsedFile)
{
ReadFile(parsedFile);
return 0;
}
- Если для
--file
не было указано значение, он выводит доступные ошибки синтаксического анализа и возвращает1
код выхода:
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
- Метод
ReadFile
считывает указанный файл и отображает его содержимое в консоли:
static void ReadFile(FileInfo file)
{
foreach (string line in File.ReadLines(file.FullName))
{
Console.WriteLine(line);
}
}
Тестирование приложения
При разработке приложения командной строки вы можете использовать один из следующих способов для тестирования:
dotnet build
Выполните команду, а затем откройте командную строку в папке scl/bin/Debug/net9.0, чтобы запустить исполняемый файл:dotnet build cd bin/Debug/net9.0 scl --file scl.runtimeconfig.json
Используйте
dotnet run
и передайте значения параметров в приложение вместо командыrun
, включив их после--
, как показано в следующем примере:dotnet run -- --file bin/Debug/net9.0/scl.runtimeconfig.json
В этом руководстве предполагается, что вы используете первый из этих вариантов.
При запуске приложения отображается содержимое файла, указанного параметром --file
.
{
"runtimeOptions": {
"tfm": "net9.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "9.0.0"
}
}
}
Но что произойдет, если вы попросите систему отобразить справку, предоставив --help
? Ничего не выводится в консоль, так как приложение пока не обрабатывает сценарий, в котором --file
не указано, и ошибки синтаксического анализа отсутствуют.
Анализ аргументов и вызов parseResult
System.CommandLine позволяет указать действие, вызываемое при успешном анализе заданного символа (команды, директивы или параметра). Действие — это делегат, который принимает System.CommandLine.ParseResult
параметр и возвращает int
код выхода (асинхронные действия также доступны). Код выхода возвращается методом System.CommandLine.Parsing.ParseResult.Invoke
и может использоваться для указания того, выполнена ли команда успешно или нет.
Замените содержимое файла Program.cs кодом, приведенным ниже.
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); } } }
Предыдущий код:
Указывает, что
ReadFile
это метод, который будет вызываться при вызове корневой команды:rootCommand.SetAction(parseResult => { FileInfo parsedFile = parseResult.GetValue(fileOption); ReadFile(parsedFile); return 0; });
args
Анализирует результат и вызывает результат:ParseResult parseResult = rootCommand.Parse(args); return parseResult.Invoke();
При запуске приложения отображается содержимое файла, указанного параметром --file
.
Что произойдет, если вы попросите его отобразить справку, предоставив --help
?
scl --help
Следующие выходные данные печатаются:
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
по умолчанию предоставляет параметр справки, параметр версии и директиву "Предложить".
ParseResult.Invoke
Метод отвечает за вызов действия обработанного символа. Это может быть действие, явно предназначенное для нашей команды, или действие, предназначенное для помощи и определенное System.CommandLine
для System.CommandLine.Help.HelpOption
. Кроме того, при обнаружении ошибок синтаксического анализа он выводит их в стандартную ошибку, печатает стандартные выходные данные и возвращает 1
код выхода:
scl --invalid bla
Unrecognized command or argument '--invalid'.
Unrecognized command or argument 'bla'.
Добавление подкоманда и параметров
В этом разделе вы:
- Создайте дополнительные параметры.
- Создайте подкоманда.
- Назначьте новые параметры новой подкоманде.
Новые параметры позволяют настроить цвета переднего плана и фона текста и скорость чтения. Эти возможности будут использоваться для чтения коллекции цитат, поступающих из руководства консольного приложения телеcуфлера.
Скопируйте файл sampleQuotes.txt из репозитория GitHub для этого примера в каталог проекта. Сведения о том, как скачать файлы, см. в инструкциях Samples and Tutorials.
Откройте файл проекта и добавьте элемент
<ItemGroup>
непосредственно перед закрывающим тегом</Project>
:<ItemGroup> <Content Include="sampleQuotes.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup>
Добавление этой разметки приводит к копированию текстового файла в папку bin/debug/net9.0 при сборке приложения. Таким образом, при запуске исполняемого файла в этой папке можно получить доступ к файлу по имени, не указывая путь к папке.
В Program.csпосле кода, создающего параметр
--file
, создайте параметры для управления скоростью чтения и цветами текста: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." };
После строки, которая создает корневую команду, удалите код, который добавляет параметр
--file
к ней. Вы удаляете его здесь, поскольку добавите его в новую подкоманду.После строки, создающей корневую команду, создайте подкоманду
read
. Добавьте параметры в эту подкоманду (с помощью синтаксиса инициализатора коллекции, а не свойстваOptions
) и добавьте подкоманду в корневую команду.Command readCommand = new("read", "Read and display the file.") { fileOption, delayOption, fgcolorOption, lightModeOption }; rootCommand.Subcommands.Add(readCommand);
Замените код
SetAction
следующим кодомSetAction
для нового подкоманда:readCommand.SetAction(parseResult => ReadFile( parseResult.GetValue(fileOption), parseResult.GetValue(delayOption), parseResult.GetValue(fgcolorOption), parseResult.GetValue(lightModeOption)));
Вы больше не вызываете
SetAction
в корневой команде, потому что корневая команда больше не нуждается в действии. При наличии вложенных команд обычно необходимо указать один из вложенных команд при вызове приложения командной строки.Замените
ReadFile
метод действия следующим кодом: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)); } }
Теперь приложение выглядит следующим образом:
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));
}
}
}
Протестируйте новую подкоманду
Теперь, если вы пытаетесь запустить приложение без указания подкоманда, появится сообщение об ошибке, за которым следует сообщение справки, указывающее доступную подкоманда.
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.
Текст справки для субкоманда read
показывает, что доступны четыре варианта. Отображаются допустимые значения для перечисления.
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
Запустите подкоманда read
, указав только параметр --file
, и вы получите значения по умолчанию для других трех параметров.
scl read --file sampleQuotes.txt
Задержка по умолчанию в 42 миллисекундах для каждого символа приводит к медленной скорости чтения. Вы можете ускорить его, установив --delay
на более низкое число.
scl read --file sampleQuotes.txt --delay 0
Для задания цветов текста можно использовать --fgcolor
и --light-mode
:
scl read --file sampleQuotes.txt --fgcolor red --light-mode
Укажите недопустимое значение для --delay
и вы получите сообщение об ошибке:
scl read --file sampleQuotes.txt --delay forty-two
Cannot parse argument 'forty-two' for option '--int' as expected type 'System.Int32'.
Укажите недопустимое значение для --file
и вы получите исключение:
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''
Добавление подкоманд и настраиваемой проверки
В этом разделе создается окончательная версия приложения. По завершении приложение будет иметь следующие команды и параметры:
- корневая команда с рекурсивным параметром, именуемым
--file
- команда
quotes
- команда
read
с параметрами с именем--delay
,--fgcolor
и--light-mode
- команда
add
с аргументами с именемquote
иbyline
- команда
delete
с параметром с именем--search-terms
- команда
- команда
* Рекурсивный параметр доступен команде, которой он назначен, и рекурсивно всем её подкомандам.
Ниже приведен пример входных данных командной строки, который вызывает каждую из доступных команд со своими параметрами и аргументами:
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"
В Program.csзамените код, который создает параметр
--file
следующим кодом: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); } } };
Этот код использует
System.CommandLine.Parsing.ArgumentResult
для предоставления пользовательского синтаксического анализа, проверки и обработки ошибок.Без этого кода отсутствие файлов сообщается с вызовом исключения и трассировкой стека. В этом коде отображается только указанное сообщение об ошибке.
Этот код также задает значение по умолчанию, поэтому
DefaultValueFactory
устанавливается на пользовательский метод синтаксического анализа.После кода, создающего
lightModeOption
, добавьте параметры и аргументы для командadd
и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." };
Параметр
xref:System.CommandLine.Option.AllowMultipleArgumentsPerToken
позволяет опустить имя параметра--search-terms
при указании элементов в списке после первого. В нем приведены следующие примеры эквивалента входных данных командной строки:scl quotes delete --search-terms David "You can do" scl quotes delete --search-terms David --search-terms "You can do"
Замените код, который создает корневую команду и команду
read
следующим кодом: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);
Этот код вносит следующие изменения:
Удаляет параметр
--file
из командыread
.Добавляет параметр
--file
в качестве рекурсивной опции к корневой команде.Создает команду
quotes
и добавляет ее в корневую команду.Добавляет команду
read
в командуquotes
вместо корневой команды.Создает команды
add
иdelete
и добавляет их в командуquotes
.
Результатом является следующая иерархия команд:
- Корневая команда
quotes
read
add
delete
Теперь приложение реализует рекомендуемый шаблон, в котором родительская команда (
quotes
) указывает область или группу, а его дочерние команды (read
,add
,delete
) являются действиями.Рекурсивные параметры применяются к команде и рекурсивно к подкомандам. Так как
--file
находится в корневой команде, она будет доступна автоматически во всех подкомандах приложения.После кода
SetAction
добавьте новый кодSetAction
для новых подкоманд.deleteCommand.SetAction(parseResult => DeleteFromFile( parseResult.GetValue(fileOption), parseResult.GetValue(searchTermsOption))); addCommand.SetAction(parseResult => AddToFile( parseResult.GetValue(fileOption), parseResult.GetValue(quoteArgument), parseResult.GetValue(bylineArgument)) );
Подкоманда
quotes
не имеет действия, поскольку это не команда-узел. Подкомандыread
,add
иdelete
являются конечными командами подquotes
, и для каждой из них вызываетсяSetAction
.Добавьте действия для
add
и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}"); }
Готовое приложение выглядит следующим образом:
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}");
}
}
Выполните сборку проекта, а затем выполните следующие команды.
Отправьте несуществующий файл в --file
с помощью команды read
, и вы получите сообщение об ошибке вместо исключения и трассировки стека:
scl quotes read --file nofile
File does not exist
Попробуйте запустить подкоманда quotes
, и вы получите сообщение, которое направляет вас на использование read
, add
или 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.
Запустите подкоманда add
, а затем просмотрите конец текстового файла, чтобы увидеть добавленный текст:
scl quotes add "Hello world!" "Nancy Davolio"
Запустите подкоманда delete
со строками поиска с начала файла, а затем просмотрите начало текстового файла, чтобы узнать, где был удален текст:
scl quotes delete --search-terms David "You can do" Antoine "Perfection is achieved"
Примечание.
Если вы работаете в папке bin/debug/net9.0 , в этой папке будет находиться файл с изменениями из add
и delete
команд. Копия файла в папке проекта остается неизменной.
Дальнейшие действия
В этом руководстве вы создали простое приложение командной строки, использующее System.CommandLine
. Дополнительные сведения о библиотеке см. в System.CommandLine обзоре.