概要
System.CommandLine ライブラリには、コマンドライン入力の解析やヘルプ テキストの表示など、コマンドライン アプリで一般的に必要とされる機能が用意されています。
本記事作成時はSystem.CommandLineパッケージはプレリリース版でした。
本記事編集時の最新は2.0.3
やってみよう。
NuGet
プレリリース版
基本
Program.cs
// ルートコマンドを設定
var root = new RootCommand("コマンド全体の説明");
// ルートコマンドの動作を設定
root.SetHandler(() => System.Console.WriteLine("実行されました。"));
// 実行
await root.InvokeAsync(args);
実行してみます。
> TestCommandLine
実行されました。
ヘルプを表示します。
> TestCommandLine --help
Description:
コマンド全体の説明
Usage:
TestCommandLine [options]
Options:
--version Show version information
-?, -h, --help Show help and usage information
バージョンを表示します。
> TestCommandLine --version
1.0.0
応用
Program.cs
// ルートコマンドを設定
var root = new RootCommand("コマンド全体の説明");
// グローバルオプションに--verboseオプション(値なし)を設定
var verboseOption = new Option<bool>("--verbose", "verboseオプションの説明");
verboseOption.AddAlias("-v");
verboseOption.Arity = ArgumentArity.Zero;
root.AddGlobalOption(verboseOption);
// コマンド1
var cmd1 = new Command("cmd1", "コマンド1の説明");
root.Add(cmd1);
// コマンド1の引数(省略可)
var cmd1arg1 = new Argument<string>("arg1", "コマンド1-引数1 の説明");
cmd1arg1.SetDefaultValue("arg1Value");
cmd1.AddArgument(cmd1arg1);
// コマンド1のオプション(省略可)
var cmd1op1 = new Option<string>("--op1", "コマンド1-オプション1 の説明");
cmd1op1.SetDefaultValue("op1Value");
cmd1.AddOption(cmd1op1);
// コマンド1の動作
cmd1.SetHandler((cmd1arg1Value, cmd1op1Value, verboseOptionValue) =>
{
Console.WriteLine($"cmd1 arg1 = {cmd1arg1Value} --op1 = {cmd1op1Value} --verbose = {verboseOptionValue}");
}, cmd1arg1, cmd1op1, verboseOption);
// コマンド2
var cmd2 = new Command("cmd2", "コマンド2の説明");
root.Add(cmd2);
// コマンド2の引数(必須)
var cmd2arg1 = new Argument<FileInfo>("arg1", "コマンド2-引数1 の説明");
cmd2.AddArgument(cmd2arg1);
// コマンド2の動作
cmd2.SetHandler((file, verboseOptionValue) =>
{
Console.WriteLine($"cmd2 arg1 = {file.FullName} --verbose = {verboseOptionValue}");
}, cmd2arg1, verboseOption);
// 実行
await root.InvokeAsync(args);
全体のヘルプ
> TestCommandLine --help
Description:
コマンド全体の説明
Usage:
TestCommandLine [command] [options]
Options:
-v, --verbose verboseオプションの説明
--version Show version information
-?, -h, --help Show help and usage information
Commands:
cmd1 <arg1> コマンド1の説明 [default: arg1Value]
cmd2 <arg1> コマンド2の説明
cmd1のヘルプ
> TestCommandLine cmd1 --help
Description:
コマンド1の説明
Usage:
TestCommandLine cmd1 [<arg1>] [options]
Arguments:
<arg1> コマンド1-引数1 の説明 [default: arg1Value]
Options:
--op1 <op1> コマンド1-オプション1 の説明 [default: op1Value]
-v, --verbose verboseオプションの説明
-?, -h, --help Show help and usage information
cmd1を実行 (引数・オプションなし)
> TestCommandLine cmd1
cmd1 arg1 = arg1Value --op1 = op1Value --verbose = False
cmd1を実行 (引数・オプションあり)
> TestCommandLine cmd1 abc --op1 def -v
cmd1 arg1 = abc --op1 = def --verbose = True
cmd2のヘルプ
> TestCommandLine cmd2 --help
Description:
コマンド2の説明
Usage:
TestCommandLine cmd2 <arg1> [options]
Arguments:
<arg1> コマンド2-引数1 の説明
Options:
-v, --verbose verboseオプションの説明
-?, -h, --help Show help and usage information
cmd2の実行(引数なし)
>TestCommandLine cmd2
Required argument missing for command: 'cmd2'.
cmd2の実行(引数あり)
C:\temp> TestCommandLine cmd2 hoge.txt
cmd2 arg1 = C:\temp\hoge.txt --verbose = False
終了コードを返したい
Program.cs
cmd2.SetHandler((file, verboseOptionValue) =>
{
bool result = true;
// ~省略~
//コマンドの戻り値
return Task.FromResult(result ? 0 : 1);
}, cmd2arg1, verboseOption);
// 実行
return await root.InvokeAsync(args);
解析だけしたい
Program.cs
// 実行
//await root.InvokeAsync(args);
var result = root.Parse(args);
if(result.Errors.Count > 0)
{
Console.WriteLine(result.Errors.Select(r => r.Message).Aggregate((r1, r2) => $"{r1}\r\n{r2}"));
}
else if (result.CommandResult.Command == cmd1)
{
Console.WriteLine(result.CommandResult.GetValueForArgument(cmd1arg1));
Console.WriteLine(result.CommandResult.GetValueForOption(cmd1op1));
Console.WriteLine(result.CommandResult.GetValueForOption(verboseOption));
}
else if (result.CommandResult.Command == cmd2)
{
Console.WriteLine(result.CommandResult.GetValueForArgument(cmd2arg1));
Console.WriteLine(result.CommandResult.GetValueForOption(verboseOption));
}
2.0.3
プレリリース版から結構変更がはいりました。
- SetHandler ⇒ SetAction
- AddArgument ⇒ Arguments.Add
- AddOption ⇒ Options.Add
Program.cs
using System;
using System.CommandLine;
Option<bool> rootOption = new("--verbose")
{
Description = "詳細情報を表示する"
};
RootCommand rootCommand = new("System.CommandLine 2.0.3のサンプル");
rootCommand.Options.Add(rootOption);
rootCommand.SetAction(parseResult =>
{
bool isVerbose = parseResult.GetValue(rootOption);
if(isVerbose)
{
Console.WriteLine("rootCommand");
}
return 0;
});
Command subCommand1 = new("SubCommand1", "サブコマンド1の説明");
rootCommand.Subcommands.Add(subCommand1);
subCommand1.Options.Add(rootOption);
subCommand1.SetAction(parseResult =>
{
bool IsVerbose = parseResult.GetValue(rootOption);
if(IsVerbose)
{
Console.WriteLine("subCommand1");
}
return 0;
});
Argument<string> sub2Argument = new("Sub2Aargument")
{
Description = "サブコマンド2の引数"
};
Command subCommand2 = new("SubCommand2", "サブコマンド2の説明");
rootCommand.Subcommands.Add(subCommand2);
subCommand2.Arguments.Add(sub2Argument);
subCommand2.SetAction(parseResult =>
{
string? sub2ArgumentValue = parseResult.GetValue(sub2Argument);
if(!string.IsNullOrEmpty(sub2ArgumentValue))
{
Console.WriteLine(sub2ArgumentValue);
}
return 0;
});
ParseResult parseResult = rootCommand.Parse(args);
return parseResult.Invoke();
PS C:\work\TestCommandLine> dotnet run hogehoge
認識されないコマンドまたは引数 'hogehoge'.
Description:
System.CommandLine 2.0.3のサンプル
使用法:
TestCommandLine [command] [options]
オプション:
--verbose 詳細情報を表示する
-?, -h, --help Show help and usage information
--version バージョン情報を表示する
コマンド:
SubCommand1 サブコマンド1の説明
SubCommand2 <Sub2Aargument> サブコマンド2の説明