共用方式為


如何在 System.CommandLine 中定義命令、選項和引數

重要

System.CommandLine 目前為預覽版,而此文件適用於版本 2.0 搶鮮版 (Beta) 4。 部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

本文說明如何在使用 System.CommandLine 程式庫建置的命令列應用程式中,定義命令選項引數。 若要建置完整的應用程式來說明這些技術,請參閱開始使用 System.CommandLine教學課程。

如需有關如何設計命令列應用程式命令、選項和引數的指引,請參閱設計指引

定義根命令

每個命令列應用程式都有一個參考可執行檔本身的根命令。 如果您有一個不含子命令、選項或引數的應用程式,叫用程式碼的最簡單案例會如下所示:

using System.CommandLine;

class Program
{
    static async Task Main(string[] args)
    {
        var rootCommand = new RootCommand("Sample command-line app");

        rootCommand.SetHandler(() =>
        {
            Console.WriteLine("Hello world!");
        });

        await rootCommand.InvokeAsync(args);
    }
}

定義子命令

命令可以有稱為「子命令」或「動詞」的下層命令,而且可以視需要巢狀多個層級。 您可以新增子命令,如下列範例所示:

var rootCommand = new RootCommand();
var sub1Command = new Command("sub1", "First-level subcommand");
rootCommand.Add(sub1Command);
var sub1aCommand = new Command("sub1a", "Second level subcommand");
sub1Command.Add(sub1aCommand);

此範例中最內部的子命令可以透過類似如下的方式叫用:

myapp sub1 sub1a

定義選項

命令處理常式方法通常具有參數,而且其值可能來自命令列選項。 下列範例會建立兩個選項,並將其新增至根命令。 選項名稱包含雙連字號前置詞,這在 POSIX CLI 中很常見。 命令處理常式程式碼會顯示這些選項的值:

var delayOption = new Option<int>
    (name: "--delay",
    description: "An option whose argument is parsed as an int.",
    getDefaultValue: () => 42);
var messageOption = new Option<string>
    ("--message", "An option whose argument is parsed as a string.");

var rootCommand = new RootCommand();
rootCommand.Add(delayOption);
rootCommand.Add(messageOption);

rootCommand.SetHandler((delayOptionValue, messageOptionValue) =>
    {
        Console.WriteLine($"--delay = {delayOptionValue}");
        Console.WriteLine($"--message = {messageOptionValue}");
    },
    delayOption, messageOption);

以下示範上述範例程式碼中的命令列輸入,以及產生的輸出:

myapp --delay 21 --message "Hello world!"
--delay = 21
--message = Hello world!

全域選項

若要將選項一次新增至一個命令,請使用 AddAddOption 方法,如上述範例所示。 若要將選項新增至命令,並以遞迴方式新增至其所有子命令,請使用 AddGlobalOption 方法,如下列範例所示:

var delayOption = new Option<int>
    ("--delay", "An option whose argument is parsed as an int.");
var messageOption = new Option<string>
    ("--message", "An option whose argument is parsed as a string.");

var rootCommand = new RootCommand();
rootCommand.AddGlobalOption(delayOption);
rootCommand.Add(messageOption);

var subCommand1 = new Command("sub1", "First level subcommand");
rootCommand.Add(subCommand1);

var subCommand1a = new Command("sub1a", "Second level subcommand");
subCommand1.Add(subCommand1a);

subCommand1a.SetHandler((delayOptionValue) =>
    {
        Console.WriteLine($"--delay = {delayOptionValue}");
    },
    delayOption);

await rootCommand.InvokeAsync(args);

上述程式碼會將 --delay 新增為根命令的全域選項,而且可在 subCommand1a 的處理常式中使用。

定義引數

引數會定義並新增至選項之類的命令。 下列範例類似於選項範例,但會定義引數而非選項:

var delayArgument = new Argument<int>
    (name: "delay",
    description: "An argument that is parsed as an int.",
    getDefaultValue: () => 42);
var messageArgument = new Argument<string>
    ("message", "An argument that is parsed as a string.");

var rootCommand = new RootCommand();
rootCommand.Add(delayArgument);
rootCommand.Add(messageArgument);

rootCommand.SetHandler((delayArgumentValue, messageArgumentValue) =>
    {
        Console.WriteLine($"<delay> argument = {delayArgumentValue}");
        Console.WriteLine($"<message> argument = {messageArgumentValue}");
    },
    delayArgument, messageArgument);

await rootCommand.InvokeAsync(args);

以下示範上述範例程式碼中的命令列輸入,以及產生的輸出:

myapp 42 "Hello world!"
<delay> argument = 42
<message> argument = Hello world!

未定義預設值的引數 (例如上述範例中的 messageArgument) 會被視為必要引數。 如果未提供必要引數,則會顯示錯誤訊息,而且不會呼叫命令處理常式。

定義別名

命令和選項都支援別名。 您可以呼叫 AddAlias,將別名新增至選項:

var option = new Option("--framework");
option.AddAlias("-f");

如果提供此別名,則下列命令列會相等:

myapp -f net6.0
myapp --framework net6.0

命令別名的運作方式相同。

var command = new Command("serialize");
command.AddAlias("serialise");

此程式碼會讓下列命令列相等:

myapp serialize
myapp serialise

建議您盡可能將定義的選項別名數目減到最少,並避免特別定義特定別名。 如需詳細資訊,請參閱簡短格式別名

必要選項

若要讓選項成為必要,請將其 IsRequired 屬性設定為 true,如下列範例所示:

var endpointOption = new Option<Uri>("--endpoint") { IsRequired = true };
var command = new RootCommand();
command.Add(endpointOption);

command.SetHandler((uri) =>
    {
        Console.WriteLine(uri?.GetType());
        Console.WriteLine(uri?.ToString());
    },
    endpointOption);

await command.InvokeAsync(args);

命令說明的選項區段指出選項為必要:

Options:
  --endpoint <uri> (REQUIRED)
  --version               Show version information
  -?, -h, --help          Show help and usage information

如果此範例應用程式的命令列不包含 --endpoint,則會顯示錯誤訊息,而且不會呼叫命令處理常式:

Option '--endpoint' is required.

如果必要選項具有預設值,則不需要在命令列上指定選項。 在此情況下,預設值會提供必要選項值。

隱藏命令、選項和引數

您可能既想支援命令、選項或引數,又想避免使用者輕易就能探索到這些項目。 例如,這可能是已被取代的功能、系統管理功能或預覽功能。 使用 IsHidden 屬性可防止使用者利用 TAB 鍵自動完成或說明來探索這類功能,如下列範例所示:

var endpointOption = new Option<Uri>("--endpoint") { IsHidden = true };
var command = new RootCommand();
command.Add(endpointOption);

command.SetHandler((uri) =>
    {
        Console.WriteLine(uri?.GetType());
        Console.WriteLine(uri?.ToString());
    },
    endpointOption);

await command.InvokeAsync(args);

此範例命令說明的選項區段會省略 --endpoint 選項。

Options:
  --version               Show version information
  -?, -h, --help          Show help and usage information

設定引數元數

您可以使用 Arity 屬性來明確設定引數元數,但在大多數情況下並不需要。 System.CommandLine 會自動根據引數類型判斷引數元數:

引數類型 預設元數
Boolean ArgumentArity.ZeroOrOne
集合類型 ArgumentArity.ZeroOrMore
其他所有項目 ArgumentArity.ExactlyOne

多個引數

根據預設,當您呼叫命令時,您可以重複選項名稱,為最大元數大於一的選項指定多個引數。

myapp --items one --items two --items three

若要允許多個引數而不重複選項名稱,請將 Option.AllowMultipleArgumentsPerToken 設定為 true。 此設定可讓您輸入下列命令列。

myapp --items one two three

如果最大引數元數為 1,則相同的設定會有不同的效果。 它可讓您重複選項,但只接受該行的最後一個值。 在下列範例中,會將值 three 傳遞至應用程式。

myapp --item one --item two --item three

列出有效的引數值

若要指定選項或引數的有效值清單,請將列舉指定為選項類型,或使用 FromAmong,如下列範例所示:

var languageOption = new Option<string>(
    "--language",
    "An option that that must be one of the values of a static list.")
        .FromAmong(
            "csharp",
            "fsharp",
            "vb",
            "pwsh",
            "sql");

以下示範上述範例程式碼中的命令列輸入,以及產生的輸出:

myapp --language not-a-language
Argument 'not-a-language' not recognized. Must be one of:
        'csharp'
        'fsharp'
        'vb'
        'pwsh'
        'sql'

命令說明的選項區段會顯示有效值:

Options:
  --language <csharp|fsharp|vb|pwsh|sql>  An option that must be one of the values of a static list.
  --version                               Show version information
  -?, -h, --help                          Show help and usage information

選項和引數驗證

如需引數驗證及如何自訂的資訊,請參閱參數繫結一文中的下列各節:

另請參閱