Share via


NuGet のクロス プラットフォーム プラグイン

NuGet 4.8 以降では、クロス プラットフォーム プラグインのサポートが追加されています。 これは、厳密な一連の操作規則に準拠する必要がある、新しいプラグイン拡張モデルを構築することで実現されました。 プラグインは自己完結型の実行可能ファイル (.NET Core 環境で実行可能) で、NuGet クライアントは別のプロセスで起動されます。 これは、本当の "Write once, run anywhere" (一度プログラムを書けば、どこでも実行できる) プラグインです。 これは、すべての NuGet クライアント ツールで動作します。 プラグインには、.NET Framework (Nuget.exe、Msbuild.exe、Visual Studio)、または .NET Core (dotnet.exe) のいずれかを指定できます。 NuGet クライアントとプラグインの間のバージョン付きの通信プロトコルが定義されています。 スタートアップ ハンドシェイク中、2 つのプロセスでプロトコルのバージョンがネゴシエートされます。

すべての NuGet クライアント ツールのシナリオに対応するためには、一方に .NET Framework と .NET Core プラグインの両方が必要です。 次に、プラグインのクライアントとフレームワークの組み合わせについて説明します。

クライアント ツール フレームワーク
Visual Studio .NET Framework
dotnet.exe .NET Core
NuGet.exe .NET Framework
MSBuild.exe .NET Framework
Mono での Nuget.exe .NET Framework

機能の概要について

ワークフローの概要は、次のように表すことができます。

  1. NuGet によって使用可能なプラグインが検出されます。
  2. 該当する場合、NuGet は優先順位に従ってプラグインを反復処理し、それらを 1 つずつ起動します。
  3. NuGet では、要求を処理できる最初のプラグインが使用されます。
  4. プラグインは、不要になるとシャットダウンされます。

一般的なプラグインの要件

現在のプロトコル バージョンは "2.0.0" です。 このバージョンでは、次の要件があります。

  • Windows と Mono で実行される、信頼された有効な Authenticode 署名アセンブリがあること。 Linux および Mac でのアセンブリの実行には、特別な信頼要件はまだありません。 関連する問題
  • NuGet クライアント ツールの現在のセキュリティ コンテキストでのステートレス起動をサポートしていること。 例えば、NuGet クライアント ツールでは、後で説明するプラグイン プロトコル以外では、昇格や追加の初期化が実行されません。
  • 明示的に指定されている場合を除き、非対話型であること。
  • ネゴシエートされたプラグイン プロトコルのバージョンに準拠していること。
  • 妥当な期間内にすべての要求に応答すること。
  • 進行中の任意の操作のキャンセル要求を受け入れること。

技術仕様については、次の仕様に詳しく記載されています。

クライアントとプラグインの相互作用

NuGet クライアント ツールとプラグインは、標準ストリーム (stdin、stdout、stderr) を介して JSON と通信します。 すべてのデータは、UTF-8 でエンコードされている必要があります。 プラグインは、引数 "-Plugin" を使用して起動されます。 ユーザーがこの引数を指定せずにプラグインの実行可能ファイルを直接起動した場合、プラグインでは、プロトコル ハンドシェイクを待機する代わりに、情報メッセージを提供できます。 プロトコル ハンドシェイクのタイムアウトは 5 秒です。 プラグインは、できるだけ短時間でセットアップを完了する必要があります。 NuGet クライアント ツールは、NuGet ソースのサービス インデックスを渡すことによって、プラグインの対応している操作に対してクエリを実行します。 プラグインでは、サービス インデックスを使用して、対応しているサービスの種類が存在するかどうかを確認できます。

NuGet クライアント ツールとプラグインの間の通信は双方向です。 各要求のタイムアウトは 5 秒です。 演算に時間がかかる場合は、対応するプロセスで進行状況メッセージを送り、要求がタイムアウトしないようにする必要があります。非アクティブ状態が 1 分続くと、プラグインはアイドル状態と見なされ、シャットダウンされます。

プラグインのインストールと検出

プラグインは、規約に基づくディレクトリ構造を通じて検出されます。 CI/CD のシナリオとパワー ユーザーは、環境変数を使用して動作をオーバーライドできます。 環境変数を使用する場合、絶対パスのみが許可されます。 NUGET_NETFX_PLUGIN_PATHSNUGET_NETCORE_PLUGIN_PATHS は、5.3 以降のバージョンの NuGet ツールでのみ使用できることに注意してください。

  • NUGET_NETFX_PLUGIN_PATHS - .NET Framework ベースのツール (Nuget.exe/Msbuild.exe/Visual Studio) によって使用されるプラグインを定義します。 NUGET_PLUGIN_PATHS よりも優先されます。 (NuGet バージョン 5.3 以降のみ)
  • NUGET_NETCORE_PLUGIN_PATHS - .NET Core ベースのツール (dotnet.exe) によって使用されるプラグインを定義します。 NUGET_PLUGIN_PATHS よりも優先されます。 (NuGet バージョン 5.3 以降のみ)
  • NUGET_PLUGIN_PATHS - その NuGet プロセスに使用されるプラグインを定義します。優先度は保持されます。 この環境変数が設定されている場合は、規約に基づく検出がオーバーライドされます。 フレームワーク固有の変数のいずれかが指定されている場合は無視されます。
  • ユーザーの場所、%UserProfile%/.nuget/plugins 内の NuGet Home の場所。 この場所をオーバーライドすることはできません。 .NET Core と .NET Framework プラグインには、別のルート ディレクトリが使用されます。
フレームワーク ルート探索場所
.NET Core %UserProfile%/.nuget/plugins/netcore
.NET Framework %UserProfile%/.nuget/plugins/netfx

各プラグインは、独自のフォルダーにインストールする必要があります。 プラグインのエントリ ポイントが、インストールされるフォルダーの名前になります。また、.NET Core には .dll 拡張子、.NET Framework には .exe 拡張子が使用されます。

.nuget
    plugins
        netfx
            myPlugin
                myPlugin.exe
                nuget.protocol.dll
                ...
        netcore
            myPlugin
                myPlugin.dll
                nuget.protocol.dll
                ...

Note

現在、プラグインをインストールするためのユーザー ストーリーはありません。 これは、必要なファイルを事前に定義された場所に移動するのと同じくらい簡単です。

対応している操作

新しいプラグイン プロトコルでは、2 つの操作が対応しています。

操作名 最小プロトコル バージョン 最小 NuGet クライアント バージョン
パッケージをダウンロードする 1.0.0 4.3.0
認証 2.0.0 4.8.0

正しいランタイムでのプラグインの実行

dotnet.exe での NuGet のシナリオの場合、プラグインが dotnet.exe の特定のランタイムで実行できる必要があります。 互換性のある dotnet.exe とプラグインの組み合わせが使用されていることを確認するため、それはプラグイン プロバイダーとコンシューマーにあります。 例えば、2.0 ランタイムで dotnet.exe が 2.1 ランタイム用に記述されたプラグインを使用しようとした場合に、ユーザーの場所プラグインに問題が発生する可能性があります。

機能のキャッシュ

プラグインのセキュリティ検証とインスタンス化にはコストがかかります。 ダウンロード操作は認証操作よりもかなり頻繁に行われますが、平均的な NuGet ユーザーは認証プラグインを持っている可能性があります。 エクスペリエンスを向上させるために、指定された要求の操作要求が NuGet によってキャッシュされます。 このキャッシュは、プラグイン パスであるプラグイン キーを使用してプラグインごとに行われます。この機能キャッシュの有効期限は 30 日です。

キャッシュは %LocalAppData%/NuGet/plugins-cache に配置され、環境変数 NUGET_PLUGINS_CACHE_PATH でオーバーライドされます。 このキャッシュをクリアするには、plugins-cache オプションを使用してローカル コマンドを実行します。 all ローカル オプションでも、プラグイン キャッシュが削除されます。

プロトコル メッセージのインデックス

プロトコル バージョン "1.0.0" のメッセージ:

    • 要求方向: NuGet ->プラグイン
    • 要求にペイロードは含まれません
    • 応答なしが想定されています。 適切な応答は、プラグイン プロセスがすぐに終了するためのものです。
  1. パッケージ内のファイルのコピー

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ID とバージョン
      • パッケージ ソース リポジトリの場所
      • コピー先のディレクトリ パス
      • コピー先のディレクトリ パスにコピーするパッケージ内の列挙可能なファイル
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、コピー先ディレクトリ内のコピーされたファイルの列挙可能な完全パス
  2. パッケージ ファイル (.nupkg) のコピー

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ID とバージョン
      • パッケージ ソース リポジトリの場所
      • コピー先のファイル パス
    • 応答は以下を包含
      • 操作の結果を示す応答コード
  3. 資格情報の取得

    • 要求方向: プラグイン -> NuGet
    • 要求は以下を包含
      • パッケージ ソース リポジトリの場所
      • 現在の資格情報を使用してパッケージ ソース リポジトリから取得した HTTP 状態コード
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • ユーザー名 (使用可能な場合)
      • パスワード (使用可能な場合)
  4. パッケージ内のファイルの取得

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ID とバージョン
      • パッケージ ソース リポジトリの場所
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、パッケージ内の列挙可能なファイル パス
  5. 操作要求の取得

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ソースのサービス index.json
      • パッケージ ソース リポジトリの場所
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、列挙可能な対応している操作 (パッケージのダウンロードなど)。 プラグインでパッケージ ソースが対応していない場合、対応している操作の空のセットをプラグインが返す必要があります。

Note

このメッセージは、バージョン "2.0.0" で更新されています。 これは下位互換性を維持するため、クライアント上にあります。

  1. パッケージ ハッシュの取得

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ID とバージョン
      • パッケージ ソース リポジトリの場所
      • ハッシュ アルゴリズム
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、要求されたハッシュ アルゴリズムを使用するパッケージ ファイル ハッシュ
  2. パッケージのバージョンを取得する

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ID
      • パッケージ ソース リポジトリの場所
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、列挙可能なパッケージ バージョン
  3. サービス インデックスの取得

    • 要求方向: プラグイン -> NuGet
    • 要求は以下を包含
      • パッケージ ソース リポジトリの場所
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、サービス インデックス
  4. ハンドシェイク

    • 要求方向: NuGet <-> プラグイン
    • 要求は以下を包含
      • 現在のプラグイン プロトコルのバージョン
      • 対応している最小プラグイン プロトコルのバージョン
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、ネゴシエートされたプロトコルのバージョン。 エラーが発生すると、プラグインが終了します。
  5. Initialize

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • NuGet クライアント ツールのバージョン
      • NuGet クライアント ツールの有効な言語。 ForceEnglishOutput 設定が使用されている場合、そのことが考慮されます。
      • 既定の要求タイムアウト。プロトコルの既定値よりも優先されます。
    • 応答は以下を包含
      • 操作の結果を示す応答コード。 エラーが発生すると、プラグインが終了します。
  6. ログ

    • 要求方向: プラグイン -> NuGet
    • 要求は以下を包含
      • 要求のログ レベル
      • 記録するメッセージ
    • 応答は以下を包含
      • 操作の結果を示す応答コード。
  7. NuGet プロセスの終了の監視

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • NuGet プロセス ID
    • 応答は以下を包含
      • 操作の結果を示す応答コード。
  8. パッケージのプリフェッチ

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ID とバージョン
      • パッケージ ソース リポジトリの場所
    • 応答は以下を包含
      • 操作の結果を示す応答コード
  9. 資格情報の設定

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • パッケージ ソース リポジトリの場所
      • 最後に認識されたパッケージ ソースのユーザー名 (使用可能な場合)
      • 最後に認識されたパッケージ ソースのパスワード (使用可能な場合)
      • 最後に認識されたプロキシ ユーザー名 (使用可能な場合)
      • 最後に認識されたプロキシ パスワード (使用可能な場合)
    • 応答は以下を包含
      • 操作の結果を示す応答コード
  10. ログ レベルの設定

    • 要求方向: NuGet ->プラグイン
    • 要求は以下を包含
      • 既定のログ レベル
    • 応答は以下を包含
      • 操作の結果を示す応答コード

プロトコル バージョン "2.0.0" メッセージ

  1. 操作要求の取得
  • 要求方向: NuGet ->プラグイン

    • 要求は以下を包含
      • パッケージ ソースのサービス index.json
      • パッケージ ソース リポジトリの場所
    • 応答は以下を包含
      • 操作の結果を示す応答コード
      • 操作が成功した場合は、列挙可能な対応している操作。 プラグインでパッケージ ソースが対応していない場合、対応している操作の空のセットをプラグインが返す必要があります。

    サービス インデックスとパッケージ ソースが null の場合、プラグインは認証を使用して応答できます。

  1. 認証資格情報の取得
  • 要求方向: NuGet ->プラグイン
  • 要求は以下を包含
    • Uri
    • isRetry
    • NonInteractive
    • CanShowDialog
  • 応答は以下を包含
    • Username (ユーザー名)
    • Password (パスワード)
    • メッセージ
    • 認証の種類の一覧
    • MessageResponseCode