有时在我的PowerShell脚本中,我需要使用Add-Type -AssemblyName
访问特定的DLL。但是,我需要的DLL并不总是在机器上或GAC中。例如,我可能想要一个使用Dapper查询数据库的快速脚本。在这些情况下,我一直在复制DLL和ps1
文件。我想知道这是不是常见/一个好主意,是否有一个现有的扩展会加载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]
{
}
}
我尝试使用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或更低版本)。
我想知道是否有办法根据PowerShell的当前$PSVersionTable.CLRVersion
字段确定从哪个NuGet包文件夹加载DLL。
crownedjitter's helpful answer是一个很好的起点,Travis本人在评论中提供了额外的指示,但是让我尝试总结一下Windows PowerShell v5.1:
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是否正确:
Get-PackageSource
:
如果您找到Nugettest
源,请将其删除:
Unregister-PackageSource Nugettest
如果源Location
的nuget.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如果未安装:从头开始安装提供程序:
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
(Get-ChildItem -Filter *.dll -Recurse (Split-Path (Get-Package Dapper).Source)).FullName
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
(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.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指出,如果包具有必须加载的依赖项,则上述内容是不够的:
缺少的一个(不那么重要的)步骤是加载可能已经安装的任何依赖项。因为the Dependencies property doesn't contain enough information,似乎涉及从源目录中的
.nuspec
文件中提取.nupkg
文件,读取适当框架的<group>
,并加载这些包的程序集。