다음을 통해 공유


System.CommandLine에서 구문 분석 및 호출하기

중요합니다

System.CommandLine 는 현재 미리 보기로 제공되며, 이 설명서는 버전 2.0 베타 5용입니다. 일부 정보는 릴리스되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.

System.CommandLine 는 명령줄 구문 분석과 작업 호출 간의 명확한 구분을 제공합니다. 구문 분석 프로세스는 명령줄 입력을 구문 분석하고 구문 분석된 값(및 구문 분석 오류)이 포함된 개체를 만드는 System.CommandLine.ParseResult 작업을 담당합니다. 작업 호출 프로세스는 구문 분석된 명령, 옵션 또는 지시문과 연결된 작업을 호출합니다(인수에는 작업이 있을 수 없음).

System.CommandLine의 다음 예제에서는 명령줄 입력을 구문 분석하여 가 생성됩니다. 어떤 작업도 정의되거나 호출되지 않습니다.

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 반환되며 명령이 성공적으로 실행되었는지 여부를 나타내는 데 사용할 수 있습니다.

Get started with 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 형식은 명령줄 입력 구문 분석 결과를 나타내는 클래스입니다. 옵션 및 인수에 대한 구문 분석된 값을 가져오는 데 사용해야 합니다(작업을 사용하는지 여부에 관계없이). 구문 분석 오류 또는 일치하지 않는 토큰이 있는지 확인할 수도 있습니다.

값 가져오기

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 호출하면 구문 분석이 성공했는지 여부를 나타내는 종료 코드가 반환됩니다. 구문 분석 오류가 있는 경우 종료 코드는 0이 아니고 모든 구문 분석 오류가 표준 오류로 출력됩니다.

메서드를 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.UnmatchedTokensaptupdate 토큰을 포함합니다.

활동

작업은 명령(또는 옵션 또는 지시문)이 성공적으로 파싱될 때 호출되는 대리자입니다. 매개변수 System.CommandLine.ParseResult를 받아 int (또는 Task<int>) 종료 코드를 반환합니다. 종료 코드는 작업이 성공적으로 실행되었는지 여부를 나타내는 데 사용됩니다.

System.CommandLine는 추상 기본 클래스 System.CommandLine.CommandLineAction 와 두 개의 파생 클래스를 제공합니다.System.CommandLine.SynchronousCommandLineActionSystem.CommandLine.AsynchronousCommandLineAction 전자는 종료 코드를 반환 int 하는 동기 작업에 사용되고, 후자는 종료 코드를 반환 Task<int> 하는 비동기 작업에 사용됩니다.

동작을 정의하기 위해 파생 형식을 만들 필요가 없습니다. 이 메서드를 System.CommandLine.Command.SetAction 사용하여 명령에 대한 작업을 설정할 수 있습니다. 동기 작업은 System.CommandLine.ParseResult 매개 변수를 사용하고 int 종료 코드를 반환하는 대리자가 될 수 있습니다. 비동기 작업은 System.CommandLine.ParseResultCancellationToken 매개 변수를 받아 Task<int>를 반환하는 대리자일 수 있습니다.

rootCommand.SetAction(parseResult =>
{
    FileInfo parsedFile = parseResult.GetValue(fileOption);
    ReadFile(parsedFile);
    return 0;
});

비동기 작업

동기 및 비동기 작업은 동일한 애플리케이션에서 혼합해서는 안 됩니다. 비동기 작업을 사용하려면 애플리케이션이 위에서 아래로 비동기적이어야 합니다. 즉, 모든 작업은 비동기이어야 하며, 종료 코드를 반환하는 대리자를 허용하는 System.CommandLine.Command.SetAction 메서드를 Task<int> 사용해야 합니다. 또한 CancellationToken 작업 대리자로 전달되는 작업은 파일 I/O 작업 또는 네트워크 요청과 같이 취소할 수 있는 모든 메서드에 추가로 전달되어야 합니다.

게다가 System.CommandLine.Parsing.ParseResult.InvokeAsync 메서드를 System.CommandLine.Parsing.ParseResult.Invoke 대신 사용해야 한다는 것을 확인해야 합니다. 이 메서드는 비동기이며 종료 코드를 반환합니다 Task<int> . 또한 작업을 취소하는 데 사용할 수 있는 선택적 CancellationToken 매개 변수도 허용합니다.

앞의 코드는 SetAction 오버로드를 사용하여 ParseResultCancellationToken를 가져옵니다, 단지 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는 호출 중 모든 비동기 작업에 전달되는 를 통해 프로세스 종료(+SIGINT, SIGTERM, CancellationToken)의 신호 처리 및 관리를 가능하게 합니다. 기본적으로 사용하도록 설정되어 있으며(2초), 사용하지 않도록 설정하려면 null로 설정할 수 있습니다.

사용하도록 설정하면 지정된 시간 제한 내에 작업이 완료되지 않으면 프로세스가 종료됩니다. 예를 들어 프로세스가 종료되기 전에 상태를 저장하여 종료를 정상적으로 처리하는 데 유용합니다.

이전 단락의 샘플 코드를 테스트하려면 로드하는 데 시간이 걸리는 URL을 사용하여 명령을 실행하고 로드가 완료되기 전에 Ctrl+C를 누릅니다. macOS에서 명령+기간(.)을 누릅니다. 다음은 그 예입니다.

testapp --url https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis
The operation was aborted

종료 코드

종료 코드는 성공 또는 실패를 나타내는 작업에서 반환되는 정수 값입니다. 규칙에 따라 종료 코드는 0 성공을 의미하지만 0이 아닌 값은 오류를 나타냅니다. 명령 실행 상태를 명확하게 전달하려면 애플리케이션에서 의미 있는 종료 코드를 정의하는 것이 중요합니다.

모든 SetAction 메서드는 종료 코드를 명시적으로 제공해야 하는 대리자를 수락하는 오버로드와 int를 반환하는 오버로드를 제공합니다.

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.CommandLine구문 분석 및 유효성 검사를 사용자 지정하는 방법System.CommandLine 개요