web-dev-qa-db-ja.com

NuGetパッケージからのアセンブリの読み込み

PowerShellスクリプトで、Add-Type -AssemblyNameを使用して特定のDLLにアクセスする必要がある場合があります。ただし、必要なDLLが常にマシンまたはGACにあるとは限りません。たとえば、Dapperを使用してデータベースにクエリを実行する簡単なスクリプトが必要な場合があります。これらの場合、私は文字通りps1ファイルと一緒にDLLをコピーしています。これが一般的/良いアイデアであるかどうか、NuGetパッケージをロードし、グローバルフォルダーまたはローカルフォルダーに保存してAdd-Type -AssemblyNameを自動的に呼び出す既存の拡張機能があるかどうか疑問に思いました。

Node.jsまたはPythonでそれぞれnpmまたはpipを使用するのとよく似ています。

更新

調査を行いましたが、古いバージョンのPowerShellには何も組み込まれていません。 nuget.exeを使用して、最初から作成しようとして、ある程度の進歩がありました。

&"$(Get-Location)/nuget.exe" install $packageName -Version $version -OutputDirectory "$(Get-Location)/packages" -NoCache -NoInteractive

これにより、現在のフォルダーの「packages」フォルダーの下にある特定のパッケージ/バージョンが、その依存関係とともにダウンロードされます。ただし、すべてのフレームワークバージョンをダウンロードしているように見え、特定の環境でどのバージョンを使用するかを明確に判断する方法はありません。

それ以外の場合は、結果をループしてAdd-Typeを呼び出すことができます。

Get-ChildItem .\packages\ -Recurse -Filter "*.dll" | % {
    try
    {
        Add-Type -Path $_.FullName
    }
    catch [System.Exception]
    {
    }
}

project.jsonファイルを使用してrestoreコマンドを使用して、運が悪ければフレームワークのバージョンを制御できるかどうかを確認しました。これは私にはあまりにもハッキーです。

PowerShell5の使用に関する@crownedjitterの提案を確認します。

更新

@crownedjitterの提案を使用して、最終的にPackageManagementモジュールをNuGetに登録することができました(以下のコメントを参照)。次のコマンドを使用して、上記のNuget.exeコマンドが実行していたことを再現することができました。

Install-Package Dapper -Destination packages

明らかに、これははるかに短いです。問題は、同じ制限があることです。パッケージのすべてのフレームワークバージョンをダウンさせます。これに.NETコアが含まれていると、.NETコアフレームワークのかなりの部分がダウンします。ターゲットフレームワーク(別名、.NET 4.5.1以下)を指定する方法はないようです。

Install-Package grabbing dependencies for all .NET frameworks

PowerShellの現在の$PSVersionTable.CLRVersionフィールドに基づいて、DLLをロードするNuGetパッケージフォルダーを決定する方法があるかどうか疑問に思っています。

17
Travis Parks

crownedjitterの役立つ回答 は良い出発点であり、Travis自身がコメントで追加のポインターを提供していますが、Windows PowerShellv5.1の時点で要約

  • 前述のように、PowerShell v5 +(PowerShell Core を含む)には、プロバイダーを介して複数のリポジトリへのアクセスを提供するメタパッケージマネージャーであるPackageManagementモジュールが付属しています。 ;このモジュールのオンデマンドインストールは may v3およびv4で可能です( このダウンロード 「2016年3月のプレビュー」というラベルが付いており、最新のものです。私は見つけることができました)。

    • Find-PackageProviderは、すべての available プロバイダーを一覧表示します。
    • Get-PackageProviderインストール済みのものをリストします。
  • Install-Packageを介したNugetパッケージのインストールを有効にするのはnugetプロバイダーであり、2つの潜在的なハードルがあります。

    • nugetプロバイダーがインストールされていない可能性があります。

    • Find-Packageが結果を返すのを妨げる誤ったAPIURLでインストールされている可能性があります。

nugetプロバイダーがインストールされているかどうかをテストします

# If this fails, the provider isn't installed
Get-PackageProvider nuget

is がインストールされている場合:パッケージのソースURIが正しいことを確認します:

  • elevated PowerShellセッションを開きます。
  • Get-PackageSource:[.____を実行します。]
    • Nugettestソースを見つけた場合は、それを削除します:
      • Unregister-PackageSource Nugettest
    • ソースnuget.orgLocation列にhttps://api.nuget.org/v3/index.json(またはttps://www.nuget.org/api/v2以外のもの)が表示されている場合は、それを更新します:
      • Set-PackageSource nuget.org -NewLocation https://www.nuget.org/api/v2 -Trusted
      • 警告:これにより、Visual StudioでNuGetパッケージを参照する機能が破損する可能性があります。 https://github.com/PowerShell/PowerShellGet/issues/107 を参照してください。

インストールされていないの場合:プロバイダーを最初からインストールします

  • elevated PowerShellセッションを開きます。
  • 次のコマンドを実行します。

    Install-PackageProvider nuget
    Register-PackageSource -ProviderName nuget -name nuget.org -Location https://www.nuget.org/api/v2 -Trusted
    

上記の手順を完了すると、NuGetパッケージの検出(例:Find-Package Dapper)とインストール(例:Install-Package Dapper)が成功するはずです。

デフォルトでは、Install-PackageAllUsersスコープにインストールされます。これには昇格が必要ですが、現在のユーザーのコンテキストでのインストールは-Scope CurrentUserでのみ選択できます。


ダウンロードしたNuGetパッケージを使用

注:Add-Typeを拡張してPowerShellでNuGetパッケージを簡単に使用するには、 GitHubに関するこの提案 を参照してください。これにより、PowerShell Core6.2.0以降も必要な後続のすべての手順が不要になります。

  • 質問で示されているように、パッケージのアセンブリをAdd-Type -Path <Assembly-file-path>を使用してPowerShellセッションに手動でロードする必要があります;ただし、.NET Coreの時代には、パッケージにさまざまな.NET環境用のDLLが含まれている可能性があるため、パッケージフォルダ内の all *.dllファイルを常に盲目的にロードできるとは限りません =:

  • ダウンロードしたパッケージのファイルシステムの場所を見つけるには、.Sourceによって返される関連オブジェクトのGet-Packageプロパティをクエリします。

    (Get-Package Dapper).Source
    
  • パッケージ内のすべてのDLLのフルパスを表示するには、次のコマンドを実行します。

    (Get-ChildItem -Filter *.dll -Recurse (Split-Path (Get-Package Dapper).Source)).FullName
    
  • 完全なDLLパスを見ると、環境にロードするのに適切なDLLがわかります。Dapperパッケージの例を使用して:

    C:\Program Files\PackageManagement\NuGet\Packages\Dapper.1.50.4\lib\net451\Dapper.dll
    C:\Program Files\PackageManagement\NuGet\Packages\Dapper.1.50.4\lib\netstandard1.3\Dapper.dll
    C:\Program Files\PackageManagement\NuGet\Packages\Dapper.1.50.4\lib\netstandard2.0\Dapper.dll
    
  • 。NETStandard DLLが all .NETプラットフォームで実行されている場合、プログラムで検索できます。 (最新の)そのようなDLLとそれらをロードします:

    (Get-Item (Join-Path (Split-Path (Get-Package Dapper).Source) lib/netstandard*) | 
      Sort-Object { [version] ($_.Name -replace '^netstandard') })[-1] |
        Get-ChildItem -Filter *.dll -Recurse |
          ForEach-Object { Add-Type -LiteralPath $_.FullName }
    
    • 上記は、利用可能な最高の.NET標準バージョンDLLを探します。 特定のバージョンをターゲットにする場合、コマンドは簡単になります。例:.NET標準の場合2.0

      Get-ChildItem -Recurse -Filter *.dll -LiteralPath (Join-Path (Split-Path (Get-Package Dapper).Source) lib/netstandard2.0) |
        ForEach-Object { Add-Type -LiteralPath $_.FullName }
      

[〜#〜] bacon [〜#〜] は、パッケージにロードする必要のある依存関係がある場合、上記では不十分である

欠落している1つの(それほど重要ではない)ステップは、インストールされている可能性のある依存関係もロードすることです。 Dependenciesプロパティに十分な情報が含まれていない であるため、Sourceディレクトリの.nuspecファイルから.nupkgファイルを抽出し、適切なフレームワークの<group>を読み取り、それらのパッケージのアセンブリをロードする必要があるようです。 。

20
mklement0

Powershell 5を使用していますか?もしそうなら、それはパッケージ管理モジュールを持っているからです:

PackageManagement Module in Powershell 5

オープンソースのようです: https://github.com/OneGet

6
crownedjitter