Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это важно
System.CommandLine
в настоящее время находится в предварительной версии. Эта документация предназначена для версии 2.0 бета-версии 5.
Некоторые сведения связаны с предварительной версией продукта, который может быть существенно изменен до его выпуска. Корпорация Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых в отношении информации, предоставленной здесь.
System.CommandLine обеспечивает четкое разделение между синтаксическим анализом командной строки и вызовом действий. Процесс синтаксического анализа отвечает за синтаксический анализ входных данных командной строки и создание ParseResult объекта, содержащего проанализированные значения (и ошибки синтаксического анализа). Процесс вызова действия отвечает за вызов действия, связанного с проанализированной командой, параметром или директивой (аргументы не могут иметь действий).
В следующем примере из руководства по началу работы System.CommandLineParseResult
создается анализ входных данных командной строки. Никакие действия не определены или вызваны:
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);
}
}
}
Действие вызывается при успешном анализе заданной команды (или директивы или параметра). Действие — это делегат, который принимает 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
, они "просто работают". Использование действий позволяет сосредоточиться на логике приложения, а библиотека заботится о синтаксическом анализе и вызове действий для символов, встроенных в команду. Если вы предпочитаете, вы можете придерживаться процесса синтаксического анализа и не определять какие-либо действия (как в первом примере выше).
РезультатПарсинга
Класс ParseResult представляет результаты анализа входных данных командной строки. Его необходимо использовать для получения проанализированных значений для параметров и аргументов (независимо от того, используете ли вы действия или нет). Вы также можете проверить наличие ошибок синтаксического анализа или несовпаденных маркеров.
GetValue
Метод ParseResult.GetValue позволяет получить значения параметров и аргументов:
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
возвращает значение после синтаксического анализа или значение по умолчанию для указанного имени символа в контексте команды после синтаксического анализа (не всего дерева символов). Он принимает имя символа, а не псевдоним.
Ошибки синтаксического анализа
Свойство ParseResult.Errors содержит список ошибок синтаксического анализа, которые произошли во время процесса синтаксического анализа. Каждая ошибка представлена ParseError объектом, который содержит сведения об ошибке, например сообщение об ошибке и маркер, вызвавшего ошибку.
При вызове ParseResult.Invoke() метода возвращается код выхода, указывающий, был ли синтаксический анализ успешным или нет. Если были ошибки синтаксического анализа, код выхода не равен нулю, и все ошибки синтаксического анализа печатаются в стандартную ошибку.
Если метод не вызывается ParseResult.Invoke
, необходимо самостоятельно обрабатывать ошибки, например, распечатав их:
foreach (ParseError parseError in parseResult.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
return 1;
Несопоставленные токены
Свойство UnmatchedTokens содержит список маркеров, которые были проанализированы, но не соответствовали какой-либо настроенной команде, параметру или аргументу.
Список несовпадающих токенов полезен в командах, которые ведут себя как обёртки. Команда оболочки принимает набор маркеров и перенаправит их в другую команду или приложение. Команда sudo
в Linux является примером. Он использует имя пользователя для олицетворения и запускает команду. Например, следующая команда выполняет apt update
команду от имени пользователя admin
:
sudo -u admin apt update
Чтобы реализовать команду-оболочку, например эту, задайте для свойства System.CommandLine.Command.TreatUnmatchedTokensAsErrors
команды значение false
.
System.CommandLine.Parsing.ParseResult.UnmatchedTokens
Затем свойство будет содержать все аргументы, которые явно не принадлежат команде. В предыдущем примере ParseResult.UnmatchedTokens
будет содержать apt
и update
маркеры.
Действия
Действия — это делегаты, которые вызываются при успешном анализе команды (или параметра или директивы). Они принимают ParseResult аргумент и возвращают int
код выхода (или Task<int>
). Код выхода используется для указания того, выполнено ли действие успешно или нет.
System.CommandLine предоставляет абстрактный базовый класс CommandLineAction и два производных класса: SynchronousCommandLineAction и AsynchronousCommandLineAction. Первый используется для синхронных действий, возвращающих int
код выхода, а последний используется для асинхронных действий, возвращающих Task<int>
код выхода.
Для определения действия не требуется создать производный тип. Вы можете использовать метод SetAction, чтобы задать действие для команды. Синхронное действие может быть делегатом, который принимает ParseResult
аргумент и возвращает int
код выхода. Асинхронное действие может быть делегатом, который принимает ParseResult
и CancellationToken аргументы и возвращает значение Task<int>
.
rootCommand.SetAction(parseResult =>
{
FileInfo parsedFile = parseResult.GetValue(fileOption);
ReadFile(parsedFile);
return 0;
});
Асинхронные действия
Синхронные и асинхронные действия не должны быть смешанными в одном приложении. Если вы хотите использовать асинхронные действия, приложение должно быть асинхронным на протяжении всего. Это означает, что все действия должны быть асинхронными, и следует использовать System.CommandLine.Command.SetAction
метод, который принимает делегат, возвращающий Task<int>
код выхода. Кроме того, CancellationToken делегату действия необходимо передать все методы, которые можно отменить, например операции ввода-вывода файлов или сетевые запросы.
Кроме того, необходимо убедиться, что ParseResult.InvokeAsync(CancellationToken) метод используется вместо 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;
}
}
Время ожидания завершения процесса
ProcessTerminationTimeout позволяет сигнализировать и обрабатывать завершение процесса (CTRL+C, SIGINT
, ) 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();
}