鷲ノ巣

C# とか PowerShell とか。当ブログの記事は(特に公開直後は)頻繁に改定される場合があることをご了承ください。

.NET での CLI 処理ライブラリについて

CLI 処理ライブラリって何がいいんですかね? っていうお話です。

追記 (2019-03-25)

Microsoft が性懲りもなく新しいプロジェクトを立ち上げたようです。
github.com
あとで評価してみたいと思います。

発端


というつぶやきを目にして、引用されているこちらのブログを見てみました。
tnakamura.hatenablog.com
そちらで紹介されているのが、このパッケージ。
www.nuget.org
Microsoft 謹製ということで、安心感はあります*1が、ブログ執筆当時はともかくとして、それから1年以上経った今でも、パッケージが更新されていないというのは、(このパッケージを所管する ASP.NET Core のアクティブさに比して)不安なところがあります。*2

暗転

で、いろいろお話をしているうちに、こういう件を教えてもらいました。

Microsoft.Extensions.Commandlineの件もあってなんか乗り気じゃない

https://twitter.com/skitoy4321/status/1009726423362256898

む、その Microsoft.Extensions なんちゃらというのは、さっきのパッケージのことではないか? ということで、リンク先を見てみますと、なんか不穏なことが書いてあるわけです。
github.com

This library was only intended for usage with ASP.NET Core's tools, and not a general purpose library. After receiving bugs and questions about this, we realized that we didn't really intend to produce and support a command-line parsing library.

We will still leave the 1.0.0 and 1.1.0 versions of this library on NuGet.org, but the current plan is to stop producing new versions of this package.

The source code is still available for internal use via Microsoft.Extensions.CommandLineUtils.Sources, however we will not be publishing this library again as a general purpose library.

https://github.com/aspnet/Common/commit/2230370a3985fd1bbeebbdd904a3dd348f612d35

ぐぐる先生に放り込んでみますと

このライブラリは、汎用のライブラリではなく、ASP.NET Coreのツールでのみ使用することを目的としていました。 これに関するバグや質問を受けた後、コマンドライン解析ライブラリを実際に作成してサポートするつもりはないことに気付きました。
私たちはまだこのライブラリの1.0.0と1.1.0のバージョンをNuGet.orgのままにしていますが、現在の計画はこのパッケージの新しいバージョンの作成をやめることです。
ソースコードMicrosoft.Extensions.CommandLineUtils.Sourcesを介して内部使用することができますが、このライブラリを汎用ライブラリとして公開することはありません。

というわけで。*3
つまり、先ほどの NuGet パッケージは、もうメンテナンスされていない、ということなのですね。

なお、ASP.NET Core チームが内部的に利用するためのソースコードは、こちらにあります。
https://github.com/aspnet/Common/tree/master/shared/Microsoft.Extensions.CommandLineUtils.Sourcesgithub.com

光明

じゃあ他に何を使えばよいのか、とお困りのあなたに朗報です。


というわけで、こちら。
www.nuget.org

これは、先ほどのライブラリからフォークしたものです。
このライブラリは Microsoft 謹製ではありませんが、開発している @natemcmaster 氏は MicrosoftASP.NET Core チームの中の人です。
先ほどのパッケージの正統後継であると考えてよいでしょう。

ですから、これを使おうというのが、一つの答えです。よかったよかった。

岐路

この件についていろいろ調べていたところ、こんなリポジトリもあるのに気が付きました。
github.com
ブランチ名が "release/2.1.3xx" となっています。
おや、これはひょっとして、先日リリースされた .NET Core SDK のバージョン番号ではないですか?
www.microsoft.com
ということは、このコードは Microsoft 製品に採用されており、しかも現役で開発されているものなのではないか…と思いました。

で、調べてみると、dotnet CLI の中で使われていることがわかりました。
例えばこの辺です。

public static Command Add() =>
    Create.Command(
        "add",
        LocalizableStrings.NetAddCommand,
        Accept.ExactlyOneArgument()
              .DefaultToCurrentDirectory()
              .With(name: CommonLocalizableStrings.ProjectArgumentName,
                    description: CommonLocalizableStrings.ProjectArgumentDescription),
        AddPackageParser.AddPackage(),
        AddProjectToProjectReferenceParser.AddProjectReference(),
        CommonOptions.HelpOption());

https://github.com/dotnet/cli/blob/master/src/dotnet/commands/dotnet-add/AddCommandParser.cs#L15

この Create.Command は、先ほどのリポジトリのここを呼び出しています。

public static Command Command(
    string name,
    string help,
    ArgumentsRule arguments,
    params Option[] options) =>
    new Command(name, help, options, arguments);

https://github.com/dotnet/CliCommandLineParser/blob/master/src/source/CommandLine/Create.cs#L47

このライブラリは、Microsoft.DotNet.Cli.CommandLine.dll というアセンブリになっています。
NuGet パッケージとしては存在しないようですが、myget リポジトリにはあります。
https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.DotNet.Cli.CommandLine

ドキュメントも正式なサポートもありませんが、こちらを使ってみるのも面白いかもしれません。

というわけで。


という要望に関しては、

  • dotnet CLI 組み込みのサブコマンド(add とか build とか)は、この Microsoft.DotNet.Cli.CommandLine ライブラリ
  • dotnet ef などの ASP.NET チームが所管するコマンドは、Microsoft.Extensions.CommandLineUtils から派生した内部向けソース

が使われているということになります。
いずれも公的なサポートはありません。

なお、dotnet CLIリポジトリを見ていますと、他にもコマンドライン処理に関係しそうなコードが入っています。
たとえばこれ。
github.com
これは、Microsoft.Extensions.CommandLineUtils からコピーされたコードです。
が、現在の dotnet CLI では使用されておらず、リファクタリングの過程で消し忘れたものではないかと思われます。*4

また、Microsoft.DotNet.Cli.Utils というディレクトリもあります。
github.com
こちらには NuGet パッケージもあります。
www.nuget.org
詳細に見てはいませんが、これは汎用的なコマンドライン処理ライブラリというよりは、dotnet CLI に特化したコードであるように見受けられます。
ちょっと気になります。

墓標

余談ですが、前述の Microsoft.Extensions.CommandLineUtils パッケージの終息を受けて、代替を探す人に対し、ASP.NET Core チームの中の人が、何度か "System.CommandLine" という名前を出しています。
"System" というプリフィックスからもわかるとおり、これも MS 謹製のライブラリです。
こちらにあります。
github.com

URL に注意してください。"archived_projects" とありますね。
もともと corefxlab という、.NET Core に入るかどうかわからない実験的プロジェクトとして開発されていたものですが、正式版になることなくお蔵入りとなってしまいました。残念です。

貝殻

MS 謹製というところに重きを置かないならば、他にいくらでもライブラリはあると思います。
そうしたものの紹介は今回はやめておきます。よく知らないし。

ところで、コンソール アプリを作るのに、いちいち面倒なコマンドライン処理なんかしたくない!ということでしたら、PowerShell もいいですよ。クロスプラットフォームになりましたし。
そういえば、先日、いい本が出たと聞きました。

通称「貝殻本」といいます。
実はちょっとだけ書くのをお手伝いしました。買ってね!という強引な宣伝。

*1:俺はそういうところをすごく気にしてしまう性質なのです

*2:俺はそういう以下略

*3:ぐぐる先生すげぇ

*4:gerp しても参照されていないようでした