从NuGet包中加载程序集

时间:2016-08-31 19:28:25

标签: powershell nuget-package powershell-v4.0

有时在我的PowerShell脚本中,我需要使用Add-Type -AssemblyName访问特定的DLL。但是,我需要的DLL并不总是在机器上或GAC中。例如,我可能想要一个使用Dapper查询数据库的快速脚本。在这些情况下,我一直在复制DLL和ps1文件。我想知道这是不是常见/好主意,是否有现有的扩展程序可以加载NuGet包,然后存储在全局或本地文件夹中并自动调用Add-Type -AssemblyName

这很像分别在Node.js或Python中使用npmpip

更新

我做了一些研究,并没有内置于早期版本的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]
    {
    }
}

我尝试使用restore命令使用project.json文件来查看是否可以控制框架版本而没有运气。这对我来说太过于苛刻了。

我将查看@ crownedjitter关于使用PowerShell 5的建议。

更新

使用@ crownedjitter的建议,我最终能够使用NuGet注册PackageManagement模块(参见下面的评论)。使用以下命令,我能够重现上面Nuget.exe命令正在执行的操作:

Install-Package Dapper -Destination packages

显然,这要短得多。问题是它有同样的局限性;它降低了包的每个框架版本。如果这包括.NET核心,它会带来很多.NET核心框架!似乎没有办法指定目标框架(a.k.a,.NET 4.5.1或更低版本)。

Install-Package grabbing dependencies for all .NET frameworks

我想知道是否有办法根据PowerShell的当前$PSVersionTable.CLRVersion字段确定从哪个NuGet包文件夹加载DLL。

2 个答案:

答案 0 :(得分:14)

crownedjitter's helpful answer是一个很好的起点,Travis本人在评论中提供了额外的指示,但让我尝试从Windows PowerShell v5.1开始总结

  • 如前所述,PowerShell v5 + - 包括PowerShell Core - 附带PackageManagement模块,它是一个元包管理器,可通过提供程序访问多个存储库;按需安装此模块可能可以在v3和v4中使用(this download标记为“2016年3月预览”,这是我能找到的最新版本。)

    • Find-PackageProvider列出了所有可用的提供商。
    • Get-PackageProvider列出已安装的
  • nuget提供商通过Install-Package 启用安装Nuget软件包,并且有两个潜在障碍:< / p>

    • 可能未安装nuget提供程序。

    • 可能安装了错误的API网址,导致Find-Package无法返回结果。

测试nuget提供程序是否已安装

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

如果安装 :验证包源URI是否正确:

  • 打开提升 PowerShell会话。
  • 运行Get-PackageSource
    • 如果您找到Nugettest来源,请将其删除:
      • Unregister-PackageSource Nugettest
    • 如果来源Location的{​​{1}}列显示nuget.org(或https://api.nuget.org/v3/index.json以外的其他内容),请更新它:

如果未安装:从头开始安装提供商

  • 打开提升 PowerShell会话。
  • 运行以下命令:

    Set-PackageSource nuget.org -NewLocation https://www.nuget.org/api/v2 -Trusted

完成上述步骤后,NuGet包的发现(例如Install-PackageProvider nuget Register-PackageSource -ProviderName nuget -name nuget.org -Location https://www.nuget.org/api/v2 -Trusted )和安装(例如Find-Package Dapper)应该会成功。

默认情况下,Install-Package Dapper会安装到Install-Package范围,这需要提升,但您可以选择仅使用AllUsers在当前用户的上下文中进行安装。

使用下载的NuGet包

注意:通过扩展-Scope CurrentUser,可以更轻松地查看this suggestion on GitHub以便在PowerShell中使用NuGet包,从而避免了对PowerShell Core 6.2.0中仍需要的所有后续步骤的需求

  • 正如问题中所示,您需要使用Add-Type 手动将软件包的程序集加载到PowerShell会话中;但是,在.NET Core时代,软件包可能有不同.NET环境的DLL,所以你不能总是盲目地在软件包文件夹中加载所有 Add-Type -Path <assembly-file-path>文件

  • 要发现已下载包的文件系统位置,请查询*.dll返回的相关对象的.Source属性:

    Get-Package
  • 查看软件包中所有DLL的完整路径,请运行以下命令:

    (Get-Package Dapper).Source
    
  • 查看完整的DLL路径应该告诉您哪些DLL是适合您的环境加载的DLL;使用(Get-ChildItem -Filter *.dll -Recurse (Split-Path (Get-Package Dapper).Source)).FullName 包的示例:

    Dapper
  • 但是,鉴于 .NET标准 DLL在所有 .NET平台上运行,您可以通过编程方式查找(最新) )这样的DLL并加载它们:

    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
    
    • 上面介绍最高可用 .NET标准版DLL;如果要定位特定版本,命令会变得更容易;例如,对于.NET Standard (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 }

      2.0

答案 1 :(得分:6)

您使用的是Powershell 5吗?因为如果你是,它有一个包管理模块:

PackageManagement Module in Powershell 5

它似乎是开源的:https://github.com/OneGet