powershell - 如何将 StackExchange.Redis.dll 加载到 powershell 中?

标签 powershell stackexchange.redis

我正在尝试创建一个 powershell 脚本来清除 redis 缓存,它位于 Azure 中,但我认为这不相关。我已经看到了两个示例,我正在尝试复制人们将 StackExchange.Redis.dll 加载到脚本中的位置: https://www.powershellgallery.com/packages/Saritasa.Redis/1.2.0/Content/Saritasa.Redis.psm1Clearing Azure Redis Cache using PowerShell during deployment .

我已从 nuget.org 下载了当前的 StackExchange.Redis.dll。我尝试在两台服务器上加载它,一台安装了.Net 4.61,另一台安装了.Net 4.8。我在两者上都遇到了同样的问题。

如果我尝试使用 [System.Reflection.Assembly]::LoadFrom 我得到如下:

PS E:\redis\stackexchange.redis.2.2.88\lib\net461> dir


    Directory: E:\redis\stackexchange.redis.2.2.88\lib\net461


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        05/11/2021     00:42     637440 StackExchange.Redis.dll
-a---        05/11/2021     00:42     705989 StackExchange.Redis.xml


PS E:\redis\stackexchange.redis.2.2.88\lib\net461> [System.Reflection.Assembly]::LoadFrom("E:\redis\stackexchange.redis.
2.2.88\lib\net461\StackExchange.Redis.dll")

GAC    Version        Location
---    -------        --------
False  v4.0.30319     E:\redis\stackexchange.redis.2.2.88\lib\net461\StackExchange.Redis.dll


PS E:\redis\stackexchange.redis.2.2.88\lib\net461> [StackExchange.Redis.ConnectionMultiplexer]::Connect($myConnectionStr
ing)
Unable to find type [StackExchange.Redis.ConnectionMultiplexer]: make sure that the assembly containing this type is
loaded.
At line:1 char:1
+ [StackExchange.Redis.ConnectionMultiplexer]::Connect($myConnectionString)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (StackExchange.R...tionMultiplexer:TypeName) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

PS E:\redis\stackexchange.redis.2.2.88\lib\net461>

如果我尝试使用Add-Type,我会得到:

PS E:\redis\stackexchange.redis.2.2.88\lib\net461> Add-Type -AssemblyName .\StackExchange.Redis.dll
Add-Type : Could not load file or assembly '.\\StackExchange.Redis.dll' or one of its dependencies. The given assembly
name or codebase was invalid. (Exception from HRESULT: 0x80131047)
At line:1 char:1
+ Add-Type -AssemblyName .\StackExchange.Redis.dll
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Add-Type], FileLoadException
    + FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand

PS E:\redis\stackexchange.redis.2.2.88\lib\net461>

我查看了 nuget.org 中的依赖项,我看到一个名为 Pipelines.Sockets.Unofficial 的非 Microsoft 依赖项,我也下载了它并得到了同样的东西。还有一个完整的其他依赖项层次结构,我认为它们都是 .Net 的一部分,如果 .Net 安装在服务器上,我当然不需要全部下载它们?感谢您的帮助,我一整天都在努力!

最佳答案

我会把我学到的一些东西放在我的代码之上,以防像我这样缺乏经验的人读到这篇文章。这些点没有任何顺序:

  • 要下载供 powershell 使用的 nuget 包,最简单的方法是使用 Install-Package cmdlet,例如: Install-Package -Name System.IO.Pipelines -ProviderName NuGet -SkipDependencies -Destination C:\Stackexchange.Redis-packages -RequiredVersion 5.0.1 请注意,需要 -SkipDependency,因为如果没有它,Install-Package 会给我一条有关循环依赖项的错误消息,如 https://endjin.com/blog/2020/12/how-to-consume-a-nuget-package-in-powershell 中所述。 。你必须自己下载依赖项! 另一种方法是:在 nuget.org 中单击下载链接下载 .nupkg 文件,将其重命名为 .zip,解压文件,然后在文件资源管理器中右键单击 dll 文件,单击“属性”、“取消阻止”。

  • 我认为这个应用程序非常适合显示 DLL 的 DLL 依赖关系,它显示依赖关系的整个层次结构以及是否找到它们 https://github.com/lucasg/Dependencies

  • 在powershell中获取dll文件的程序集版本: Get-ChildItem -Filter *.dll -Recurse | Select-Object Name,@{n='FileVersion';e={$_.VersionInfo.FileVersion}},@{n='AssemblyVersion';e={[Reflection.AssemblyName]::GetAssemblyName($_.FullName).Version}} 来自Get file version and assembly version of DLL files in the current directory and all sub directories

  • 加载 DLL 时,Add-Type[System.Reflection.Assembly]::LoadFrom() 的行为不同。 Add-Type 似乎加载了有用的依赖项。如果Add-Type -Literalpath <dllFileName>失败并显示错误消息“Add-Type:无法加载一种或多种请求的类型。检索 LoaderExceptions 属性以了解更多信息 信息”你可以通过$error[0].Exception.GetBaseException().LoaderExceptions获取它正在寻找的DLL。 https://www.reddit.com/r/PowerShell/comments/7a4vw6/addtype_how_do_i_retrieve_the_loaderexceptions/

  • 为了解决层次结构中的 DLL 依赖于同一 DLL 的不同版本(这似乎很常见)的情况,这个人的解决方案简直太棒了。我找不到任何替代方案,它似乎工作完美 https://www.azurefromthetrenches.com/powershell-binding-redirects-and-visual-studio-team-services/

我使用的 DLL 我最终在文件夹中得到了这些 DLL 文件:

Name                                       FileVersion   AssemblyVersion
----                                       -----------   ---------------
Microsoft.Bcl.AsyncInterfaces.dll          6.0.21.52210  6.0.0.0
Pipelines.Sockets.Unofficial.dll           2.2.0.45337   1.0.0.0
StackExchange.Redis.dll                    2.2.88.56325  2.0.0.0
System.Buffers.dll                         4.6.28619.01  4.0.3.0
System.IO.Pipelines.dll                    5.0.120.57516 5.0.0.1
System.Memory.dll                          4.6.28619.01  4.0.1.1
System.Numerics.Vectors.dll                4.6.26515.06  4.1.4.0
System.Runtime.CompilerServices.Unsafe.dll 6.0.21.52210  6.0.0.0
System.Threading.Channels.dll              6.0.21.52210  6.0.0.0
System.Threading.Tasks.Extensions.dll      4.6.28619.01  4.2.0.1

代码尚未完成,但显示了已加载和使用的 Stackexhange.Redis DLL。

# Code to load the DLLs needed for Stackexchange.Redis.dll and clear the cache
# Basically copied from https://www.azurefromthetrenches.com/powershell-binding-redirects-and-visual-studio-team-services/

$DllPath = 'C:\Stackexchange.Redis-packages\combined DLLS'
$redisHostName = '<my cache name here>.redis.cache.windows.net'
$redisConnectionString = '<my cache name here>.redis.cache.windows.net:6380,password=<my cache password here>,ssl=True,abortConnect=False'

# Load DLL assemblies into memory, required by the event handler below
$SystemBuffersDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\System.Buffers.dll")
$SystemRuntimeCompilerServicesUnsafeDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\System.Runtime.CompilerServices.Unsafe.dll")
$SystemMemoryDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\System.Memory.dll")
$SystemSystemThreadingTasksExtensionsDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\System.Threading.Tasks.Extensions.dll")
$SystemIoPipelinesDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\System.IO.Pipelines.dll")
$MicrosoftBclAsyncInterfacesDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\Microsoft.Bcl.AsyncInterfaces.dll")
$PipelinesSocketsUnofficialDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\Pipelines.Sockets.Unofficial.dll")
$SystemThreadingChannelsDll = [System.Reflection.Assembly]::LoadFrom("$DllPath\System.Threading.Channels.dll")

# Event handler to be run when the AssemblyResolve event occurs
$onAssemblyResolveEventHandler = [System.ResolveEventHandler] {
    param($sender, $e)

    Write-Verbose "Assembly resolve event for $($e.Name)"

    $dllName = $e.Name.Split(',')[0]
  
    switch ($dllName) {
        'System.Buffers' {return $SystemBuffersDll}
        'System.Runtime.CompilerServices.Unsafe' {return $SystemRuntimeCompilerServicesUnsafeDll}
        'System.Memory' {return $SystemMemoryDll}
        'System.Threading.Tasks.Extensions' {return $SystemSystemThreadingTasksExtensionsDll}
        'Microsoft.Bcl.AsyncInterfaces' {return $MicrosoftBclAsyncInterfacesDll}
        'Pipelines.Sockets.Unofficial' {return $PipelinesSocketsUnofficialDll}
        'System.Threading.Channels' {return $SystemThreadingChannelsDll}
        'System.Numerics.Vectors' {return $SystemNumericsVectorsDll}
        'System.IO.Pipelines' {return $SystemIoPipelinesDll}
    }

    foreach($assembly in [System.AppDomain]::CurrentDomain.GetAssemblies()) {
        if ($assembly.FullName -eq $e.Name) {
        return $assembly
        }
    }
      return $null
}

# Set up the handler above to be triggered when the AssemblyResolve event occurs
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($onAssemblyResolveEventHandler)


# Load StackExchange.Redis.dll, prefer Add-Type because it seems to include dependencies, LoadFrom doesn't so might get an error later
Add-Type -LiteralPath  "$DllPath\StackExchange.Redis.dll"    

$redis = [StackExchange.Redis.ConnectionMultiplexer]::Connect("$redisConnectionString, allowAdmin=true")
$redisServer = $redis.GetServer($redisHostName, 6380)
# $rs.FlushAllDatabases(async=true)
$redisServer.FlushAllDatabases()

# Detach the event handler (not detaching can lead to stack overflow issues when closing PS)
[System.AppDomain]::CurrentDomain.remove_AssemblyResolve($onAssemblyResolveEventHandler)

关于powershell - 如何将 StackExchange.Redis.dll 加载到 powershell 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70745024/

相关文章:

.net-core - 使用 StackExchange.Redis 到 ElastiCache Redis 的 Lambda : RedisConnectionException - No connection is active/available to service this operation

powershell - ForEach-Object -Parallel 如何使用

powershell - 使用 PowerShell 安装多个 ServerRole

exception - 简单的 Try/catch 不起作用

powershell - 在 PowerCLI 中比较 2 个对象

lua - redis lua - eval 在处理 Long.MAX_VALUE 时返回错误值

.net - StackExchange Redis AddOrUpdate 处理(乐观并发)

Azure DevOps Pipeline 条件脚本参数

azure - 使用 StackExchange.Redis 存储到 Azure 托管的 Redis 缓存时出现问题

c# - 这个 Lazy<T> 被认为是单例吗?