Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это важно
System.CommandLine
в настоящее время находится в предварительной версии, и эта документация предназначена для версии 2.0 бета-версии 5.
Некоторые сведения относятся к предварительному выпуску продукта, который может быть существенно изменен до его выпуска. Корпорация Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых в отношении информации, предоставленной здесь.
System.CommandLine обеспечивает четкое разделение между синтаксическим анализом командной строки и вызовом действий. Процесс синтаксического анализа отвечает за синтаксический анализ входных данных командной строки и создание System.CommandLine.ParseResult
объекта, содержащего проанализированные значения (и ошибки синтаксического анализа). Процесс вызова действия отвечает за вызов действия, связанного с проанализированной командой, параметром или директивой (аргументы не могут иметь действий).
В следующем примере из нашего руководства как начать System.CommandLine, ParseResult
создаётся путём разбора командной строки. Никакие действия не определены или вызваны:
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);
}
}
}
Действие вызывается при успешном анализе заданной команды (или директивы или параметра). Действие — это делегат, который принимает System.CommandLine.ParseResult
параметр и возвращает int
код выхода (асинхронные действия также доступны)). Код выхода возвращается методом System.CommandLine.Parsing.ParseResult.Invoke
и может использоваться для указания того, выполнена ли команда успешно или нет.
В следующем примере из нашего руководства по началу работы System.CommandLine действие определяется для корневой команды и вызывается после разбора входных данных командной строки.
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);
}
}
}
Некоторые встроенные символы, такие как System.CommandLine.Help.HelpOption
, System.CommandLine.VersionOption
или System.CommandLine.Completions.SuggestDirective
, приходят с предопределенными действиями. Эти символы автоматически добавляются в корневую команду при ее создании, и когда вы вызываете System.CommandLine.Parsing.ParseResult
, они "просто работают". Использование действий позволяет сосредоточиться на логике приложения, а библиотека заботится о синтаксическом анализе и вызове действий для символов, встроенных в команду. Если вы предпочитаете, вы можете придерживаться процесса синтаксического анализа и не определять какие-либо действия (как в первом примере выше).
РезультатПарсинга
Тип System.CommandLine.Parsing.ParseResult
— это класс, представляющий результаты анализа входных данных командной строки. Его необходимо использовать для получения проанализированных значений для параметров и аргументов (независимо от того, используется ли действие или нет). Вы также можете проверить наличие ошибок синтаксического анализа или несовпаденных маркеров.
GetValue
Метод System.CommandLine.Parsing.ParseResult.GetValue<T>
позволяет получить значения параметров и аргументов:
int integer = parseResult.GetValue(delayOption);
string? message = parseResult.GetValue(messageOption);
Кроме того, можно получить значения по имени, но для этого необходимо указать тип нужного значения.
В следующем примере используются инициализаторы коллекции C# для создания корневой команды:
RootCommand rootCommand = new("Parameter binding example")
{
new Option<int>("--delay")
{
Description = "An option whose argument is parsed as an int."
},
new Option<string>("--message")
{
Description = "An option whose argument is parsed as a string."
}
};
Затем он использует метод GetValue
для получения значений по имени.
rootCommand.SetAction(parseResult =>
{
int integer = parseResult.GetValue<int>("--delay");
string? message = parseResult.GetValue<string>("--message");
DisplayIntAndString(integer, message);
});
Этот вариант перегрузки GetValue
возвращает значение после синтаксического анализа или значение по умолчанию для указанного имени символа в контексте команды после синтаксического анализа (не всего дерева символов). Он принимает имя символа, а не псевдоним.
Ошибки синтаксического анализа
Свойство System.CommandLine.Parsing.ParseResult.Errors
содержит список ошибок синтаксического анализа, которые произошли во время процесса синтаксического анализа. Каждая ошибка представлена System.CommandLine.Parsing.ParseError
объектом, который содержит сведения об ошибке, например сообщение об ошибке и маркер, вызвавшего ошибку.
При вызове System.CommandLine.Parsing.ParseResult.Invoke
метода возвращается код выхода, указывающий, был ли синтаксический анализ успешным или нет. Если были ошибки синтаксического анализа, код выхода не равен нулю, и все ошибки синтаксического анализа печатаются в стандартную ошибку.
Если вы не вызываете метод System.CommandLine.Parsing.ParseResult.Invoke
, необходимо самостоятельно обрабатывать ошибки, например, выводя их на экран.
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
Несопоставленные токены
Свойство System.CommandLine.Parsing.ParseResult.UnmatchedTokens
содержит список маркеров, которые были проанализированы, но не соответствовали какой-либо настроенной команде, параметру или аргументу.
Список несовпадающих токенов полезен в командах, которые ведут себя как обёртки. Команда оболочки принимает набор маркеров и перенаправит их в другую команду или приложение. Команда sudo
в Linux является примером. Он использует имя пользователя для олицетворения и запускает команду. Рассмотрим пример.
sudo -u admin apt update
Эта командная строка будет выполнять apt update
команду от имени пользователя admin
.
Чтобы реализовать команду-оболочку, например эту, задайте для свойства System.CommandLine.Command.TreatUnmatchedTokensAsErrors
команды значение false
.
System.CommandLine.Parsing.ParseResult.UnmatchedTokens
Затем свойство будет содержать все аргументы, которые явно не принадлежат команде. В предыдущем примере ParseResult.UnmatchedTokens
будет содержать apt
и update
маркеры.
Действия
Действия — это делегаты, которые вызываются при успешном анализе команды (или параметра или директивы). Они принимают System.CommandLine.ParseResult
параметр и возвращают int
код выхода (или Task<int>
). Код выхода используется для указания того, выполнено ли действие успешно или нет.
System.CommandLine предоставляет абстрактный базовый класс System.CommandLine.CommandLineAction
и два производных класса: System.CommandLine.SynchronousCommandLineAction
и System.CommandLine.AsynchronousCommandLineAction
. Первый используется для синхронных действий, возвращающих int
код выхода, а последний используется для асинхронных действий, возвращающих Task<int>
код выхода.
Для определения действия не требуется создать производный тип. Вы можете использовать метод System.CommandLine.Command.SetAction
, чтобы задать действие для команды. Синхронное действие может быть делегатом, который принимает System.CommandLine.ParseResult
параметр и возвращает int
код выхода. Асинхронное действие может быть делегатом, принимающим параметры System.CommandLine.ParseResult
и CancellationToken и возвращающим Task<int>
.
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
Асинхронные действия
Синхронные и асинхронные действия не должны быть смешанными в одном приложении. Если вы хотите использовать асинхронные действия, приложение должно быть асинхронным с верхней до нижней части. Это означает, что все действия должны быть асинхронными, и следует использовать System.CommandLine.Command.SetAction
метод, который принимает делегат, возвращающий Task<int>
код выхода. Более того, CancellationToken, переданный делегату действия, необходимо также передать всем методам, которые могут быть отменены, таким как операции ввода-вывода файлов или сетевые запросы.
Помимо этого, необходимо убедиться, что System.CommandLine.Parsing.ParseResult.InvokeAsync
метод используется вместо System.CommandLine.Parsing.ParseResult.Invoke
. Этот метод является асинхронным и возвращает Task<int>
код выхода. Он также принимает необязательный CancellationToken параметр, который можно использовать для отмены действия.
В приведенном выше коде используется перегрузка SetAction
, которая получает ParseResult и CancellationToken вместо того, чтобы просто ParseResult
:
static Task<int> Main(string[] args)
{
Option<string> urlOption = new("--url", "A URL.");
RootCommand rootCommand = new("Handle termination example") { urlOption };
rootCommand.SetAction((ParseResult parseResult, CancellationToken cancellationToken) =>
{
string? urlOptionValue = parseResult.GetValue(urlOption);
return DoRootCommand(urlOptionValue, cancellationToken);
});
return rootCommand.Parse(args).InvokeAsync();
}
public static async Task<int> DoRootCommand(
string? urlOptionValue, CancellationToken cancellationToken)
{
using HttpClient httpClient = new();
try
{
await httpClient.GetAsync(urlOptionValue, cancellationToken);
return 0;
}
catch (OperationCanceledException)
{
await Console.Error.WriteLineAsync("The operation was aborted");
return 1;
}
}
Время ожидания завершения процесса
System.CommandLine.CommandLineConfiguration.ProcessTerminationTimeout
обеспечивает возможность сигнализировать и обрабатывать завершение процесса (CTRL+CSIGINT
, SIGTERM
) с помощью CancellationToken, передаваемого каждому асинхронному действию во время вызова. Он включен по умолчанию (2 секунды), но его можно отключить, установив на null
.
Если включено, и действие не завершено в течение указанного времени ожидания, процесс будет завершен. Это полезно для корректного завершения процесса, например, путем сохранения состояния перед его остановкой.
Чтобы проверить пример кода из предыдущего абзаца, выполните команду с URL-адресом, который займет некоторое время для загрузки, и до завершения загрузки нажмите клавиши CTRL+C. В macOS нажмите клавиши Command+Period(.). Рассмотрим пример.
testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted
Коды выхода
Код выхода — это целочисленное значение, возвращаемое действием, указывающим на его успешность или сбой. По соглашению код 0
выхода означает успешность, а любое ненулевое значение указывает на ошибку. Важно определить значимые коды выхода в приложении для четкого обмена данными о состоянии выполнения команды.
Каждый SetAction
метод имеет перегрузку, которая принимает делегат, возвращающий int
код выхода, где код выхода должен быть предоставлен явно, и также перегрузку, которая возвращает 0
.
static int Main(string[] args)
{
Option<int> delayOption = new("--delay");
Option<string> messageOption = new("--message");
RootCommand rootCommand = new("Parameter binding example")
{
delayOption,
messageOption
};
rootCommand.SetAction(parseResult =>
{
Console.WriteLine($"--delay = {parseResult.GetValue(delayOption)}");
Console.WriteLine($"--message = {parseResult.GetValue(messageOption)}");
// Value returned from the action delegate is the exit code.
return 100;
});
return rootCommand.Parse(args).Invoke();
}
См. также
Как настроить синтаксический анализ и проверку в System.CommandLineSystem.CommandLine Обзор функций