プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2017/11/22

C# におけるコマンドライン引数の解析

event_note2017/11/22 6:19

C# でコマンドライン引数を解析する場合、今までだと自力で行ったりサードパーティーのパーサーを使ったりしていました。
しかし、現在では Microsoft が Microsoft.Extensions.CommandLineUtils というパーサーを用意してくれているので、それを使ってみます。

尚、.NET Core でも .NET Framework でも使えます。

環境

  • Visual Studio 2017
  • .NET Core 2.0
  • Microsoft.Extensions.CommandLineUtils 1.1.1

インストール

NuGet パッケージマネージャーコンソールから以下のコマンドでインストールできます。

PM> Install-Package Microsoft.Extensions.CommandLineUtils

簡単な使い方

using Microsoft.Extensions.CommandLineUtils;

// 中略

static void Main(string[] args)
{
    var app = new CommandLineApplication(throwOnUnexpectedArg: false)
    {
        // アプリケーション名(ヘルプの出力で使用される)
        Name = "CommandLineTest",
    };

    // ヘルプ出力のトリガーとなるオプションを指定
    app.HelpOption("-?|-h|--help");

    app.OnExecute(() =>
    {
        Console.WriteLine("Hello World!");
        return 0;
    });

    app.Execute(args);
}

動作内容は onExecute に定義します。
onExecute の引数は Func<int> なので、戻り値(エラーコード)として int の値を返す必要があります。

onExecute を定義したら app.Execute をコールすると実行されます。
引数には Main で受け取ったコマンドライン引数を渡します。

実行結果

> CommandLineTest.exe
Hello World!

> CommandLineTest.exe --help
Usage: CommandLineTest [options]

Options:
  -?|-h|--help  Show help information

コマンドの追加

上記のコードにコマンドを追加してみます。

static void Main(string[] args)
{
    var app = new CommandLineApplication(throwOnUnexpectedArg: false)
    {
        // アプリケーション名(ヘルプの出力で使用される)
        Name = "CommandLineTest",
    };

    // ヘルプ出力のトリガーとなるオプションを指定
    app.HelpOption("-?|-h|--help");

    app.OnExecute(() =>
    {
        Console.WriteLine("Hello World!");
        return 0;
    });

    app.Command("hoge", (command) =>
    {
        // 説明(ヘルプの出力で使用される)
        command.Description = "Hogeを出力する";

        // コマンドについてのヘルプ出力のトリガーとなるオプションを指定
        command.HelpOption("-?|-h|--help");

        // コマンドの引数(名前と説明を引数で渡しているが、これはヘルプ出力で使用される)
        var hogeArgs = command.Argument("[Hogeの引数]", "Hogeの引数の説明");

        command.OnExecute(() =>
        {
            var location = hogeArgs.Value != null ? $"引数あり {hogeArgs.Value}" : "引数なし";
            Console.WriteLine("Hoge: " + location);
            return 0;
        });
    });

    app.Execute(args);
}

特に説明は不要かと思います。
尚、コマンドはネストして、サブコマンドなどを作ることもできます。

実行結果

> CommandLineTest --help
Usage: CommandLineTest [options] [command]

Options:
  -?|-h|--help  Show help information

Commands:
  hoge  Hogeを出力する

Use "CommandLineTest [command] --help" for more information about a command.

> CommandLineTest hoge --help
Usage: CommandLineTest hoge [arguments] [options]

Arguments:
  [Hogeの引数]  Hogeの引数の説明

Options:
  -?|-h|--help  Show help information

> CommandLineTest hoge
Hoge: 引数なし

> CommandLineTest hoge piyo
Hoge: 引数あり piyo

オプションの指定

さらに上記のコードにオプションを追加してみます。

app.Command("hoge", (command) =>
{
    // 説明(ヘルプの出力で使用される)
    command.Description = "Hogeを出力する";

    // コマンドについてのヘルプ出力のトリガーとなるオプションを指定
    command.HelpOption("-?|-h|--help");

    // コマンドの引数(名前と説明を引数で渡しているが、これはヘルプ出力で使用される)
    var hogeArgs = command.Argument("[Hogeの引数]", "Hogeの引数の説明");

    // オプションの設定
    var hogeOptions = command.Option("-o|--option <opitons>",
        "hogeのオプション",
        CommandOptionType.MultipleValue);

    command.OnExecute(() =>
    {
        var location = hogeArgs.Value != null ? $"引数あり {hogeArgs.Value}" : "引数なし";
        Console.WriteLine("Hoge: " + location);

        foreach (var value in hogeOptions.Values)
        {
            Console.WriteLine("Hogeのオプション: " + value);
        }
        return 0;
    });
});

CommandOptionType についてはこちらに一覧があります。
何にも説明がありませんが、名前で分かると思います。

実行結果

>CommandLineTest hoge -h
Usage: CommandLineTest hoge [arguments] [options]

Arguments:
  [Hogeの引数]  Hogeの引数の説明

Options:
  -?|-h|--help           Show help information
  -o|--option <opitons>  hogeのオプション

>CommandLineTest hoge piyo -o=foo -o=bar
Hoge: 引数あり piyo
Hogeのオプション: foo
Hogeのオプション: bar

参考 URL