Powershell 从NuGet包加载程序集

Powershell 从NuGet包加载程序集,powershell,nuget-package,powershell-4.0,Powershell,Nuget Package,Powershell 4.0,有时在我的PowerShell脚本中,我需要使用Add Type-AssemblyName访问特定的DLL。然而,我需要的DLL并不总是在机器上或GAC中。例如,我可能需要一个使用Dapper查询数据库的快速脚本。在这些情况下,我一直在复制DLL以及ps1文件。我想知道这是否常见/是个好主意,是否有一个现有的扩展可以加载NuGet包,然后存储在全局或本地文件夹中,并自动调用Add Type-AssemblyName 这与在Node.js或Python中分别使用npm或pip非常相似 更新 我做了

有时在我的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]
    {
    }
}
我尝试使用
project.json
文件使用
restore
命令,看看是否可以控制框架版本。这对我来说太难了

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

更新 使用@crownedjitter的建议,我最终能够向NuGet注册PackageManagement模块(参见下面的注释)。使用以下命令,我能够重现上面的
Nuget.exe
命令所做的操作:

Install-Package Dapper -Destination packages
显然,这要短得多。问题是它有同样的局限性;它会降低包的每个框架版本。如果这包括了.NETCore,那么它会带来大量的.NETCore框架!似乎没有办法指定目标框架(又称.NET 4.5.1或更低版本)


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

是否使用PowerShell 5?因为如果是,它有一个包管理模块:

它似乎是开源的:

是一个很好的起点,Travis本人在评论中提供了额外的提示,但让我尝试总结一下自Windows PowerShell v5.1以来的情况

# If this fails, the provider isn't installed
Get-PackageProvider nuget
更新:下面的原始答案包含一些有用的常规指针,以及指向的链接,但是它显示的基于
安装包
的方法最终会出现缺陷
,因为它不考虑包的依赖关系,如 指出:

缺少的一个(不是那么简单)步骤是加载可能已经安装的任何依赖项。因为,这似乎需要从源目录中的
.nupkg
文件中提取
.nuspec
文件,读取相应框架的
,并加载这些包的程序集

以下方法解决了这一问题,但请注意,它首先需要下载并安装带有
dotnet
CLI的:

# If this fails, the provider isn't installed
Get-PackageProvider nuget
  • 为辅助项目创建文件夹,将向其中添加包并对其进行更改;e、 g:

    • 设置位置(新项目类型目录组件)
  • 在该文件夹中,创建一个虚拟库项目:

    • dotnet新类库
  • 添加对感兴趣的文件包的引用;e、 g:

    • dotnet添加程序包Dapper

    • 要引用特定版本,请添加
      -v

  • 发布虚拟项目,该项目将所有必需的DLL(包括依赖项)复制到发布文件夹中:

    • dotnet发布-c版
    • 重要
      -c
      参数的确切大小写(小写与大写)决定了相应输出文件夹的确切大小写;为了确保代码也能在区分大小写的文件系统上工作,特别是在Linux上,请确保在引用输出二进制文件的文件路径中使用完全相同的大小写
  • 测试包装的主组件是否可以加载;e、 g:

    • 添加类型-路径bin/Release/*/publish/Dapper.dll

    • 验证包的类型是否可以使用;e、 g.:
      [Dapper.DbString]::new()

现在,您可以直接从辅助项目引用主DLL,也可以将所有
bin/Release/*/publish/*.DLL
文件复制到您选择的文件夹中,并从那里引用它

以下示例脚本显示了一个脚本,该脚本根据需要下载包,并在
程序集
子文件夹中相对于脚本位置创建辅助项目

$packageName = 'Terminal.Gui'
$assembly = "$packageName.dll"
# Set to @() to get the latest stable version.
$packageVersionArgs = '-v', '1.0.0-pre.4'

$projectFolder = 'assemblies' # Subfolder for the aux. project
$assemblyPath = "$PSScriptRoot/$projectFolder/bin/Release/*/publish/$assembly"
$literalAssemblyPath = Convert-Path -ErrorAction Ignore $assemblyPath

if ($literalAssemblyPath) {
  Write-Verbose -vb "Package '$packageName' already installed. Loading main assembly: $literalAssemblyPath"
  Add-Type -ErrorAction Stop -LiteralPath $literalAssemblyPath
}
else {

  Write-Verbose -vb "Installing package '$packageName'..."

  $null = Get-Command -ErrorAction Stop -CommandType Application dotnet

  Push-Location (New-Item -ErrorAction Stop -Type Directory "$PSScriptRoot/$projectFolder")

  $null = dotnet new classlib
  $null = dotnet add package $packageName @packageVersionArgs
  $null = dotnet publish -c Release
  
  Pop-Location

  Write-Verbose -vb "Loading main assembly: $assemblyPath"  
  Add-Type -ErrorAction Stop -Path $assemblyPath
}

# Instantiate a type from the package to verify that it was loaded.
"Listing property names of a [Terminal.Gui.Button] instance:"
[Terminal.Gui.Button]::new().psobject.Properties.Name

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

    • 查找PackageProvider
      列出所有可用的提供程序
    • Get PackageProvider
      列出已安装的程序包
  • 正是
    nuget
    提供商通过
    Install Package
    实现了nuget软件包的安装,并且存在两个潜在的障碍:

    # If this fails, the provider isn't installed
    Get-PackageProvider nuget
    
    • nuget
      p
      (Get-ChildItem -Filter *.dll -Recurse (Split-Path (Get-Package Dapper).Source)).FullName
      
      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 }
      
        Get-ChildItem -Recurse -Filter *.dll -LiteralPath (Join-Path (Split-Path (Get-Package Dapper).Source) lib/netstandard2.0) |
          ForEach-Object { Add-Type -LiteralPath $_.FullName }