从NuGet包加载程序集

问题描述 投票:12回答:2

有时在我的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。

powershell nuget-package powershell-v4.0
2个回答
19
投票

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软件包,并且有两个潜在的障碍: 可能未安装nuget提供程序。 它可能安装了错误的API URL,阻止Find-Package返回结果。

测试是否安装了nuget提供程序:

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

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

  • 打开提升的PowerShell会话。
  • 运行Get-PackageSource: 如果您找到Nugettest源,请将其删除: Unregister-PackageSource Nugettest 如果源Locationnuget.org列显示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

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

  • 打开提升的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-Package安装在需要提升的AllUsers范围内,但您可以选择仅使用-Scope CurrentUser在当前用户的上下文中进行安装。


使用下载的NuGet包:

注意:请参阅this suggestion on GitHub,以便通过扩展Add-Type来更轻松地在PowerShell中使用NuGet包,这样可以避免从PowerShell Core 6.2.0开始仍然需要的所有后续步骤。

  • 如问题所示,您需要使用Add-Type -Path <assembly-file-path>手动将软件包的程序集加载到PowerShell会话中;但是,在.NET Core时代,软件包可能有不同.NET环境的DLL,因此您不能总是盲目地在软件包文件夹中加载所有*.dll文件:
  • 要发现下载包的文件系统位置,请查询.Source返回的相关对象的Get-Package属性: (Get-Package Dapper).Source
  • 要查看包中所有DLL的完整路径,请运行以下命令: (Get-ChildItem -Filter *.dll -Recurse (Split-Path (Get-Package Dapper).Source)).FullName
  • 查看完整的DLL路径应该告诉您哪些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
  • 但是,鉴于.NET标准DLL在所有.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 Standard 2.0Get-ChildItem -Recurse -Filter *.dll -LiteralPath (Join-Path (Split-Path (Get-Package Dapper).Source) lib/netstandard2.0) | ForEach-Object { Add-Type -LiteralPath $_.FullName }

BACON指出,如果包具有必须加载的依赖项,则上述内容是不够的:

缺少的一个(不那么重要的)步骤是加载可能已经安装的任何依赖项。因为the Dependencies property doesn't contain enough information,似乎涉及从源目录中的.nuspec文件中提取.nupkg文件,读取适当框架的<group>,并加载这些包的程序集。


6
投票

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

PackageManagement Module in Powershell 5

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

© www.soinside.com 2019 - 2024. All rights reserved.