有时在我的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。
答案 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
列出已安装的。 可能未安装 可能安装了错误的API网址,导致nuget
提供商通过Install-Package
启用安装Nuget软件包,并且有两个潜在障碍:< / p>
nuget
提供程序。Find-Package
无法返回结果。
测试nuget
提供程序是否已安装:
# If this fails, the provider isn't installed
Get-PackageProvider nuget
如果安装 :验证包源URI是否正确:
Get-PackageSource
:
Nugettest
来源,请将其删除:
Unregister-PackageSource Nugettest
Location
的{{1}}列显示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
完成上述步骤后,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)