从 dll 的字节数组加载程序集

Loading an assembly from a dll's Byte array

我正在尝试使用此加载程序集:

$pathToDll = "C:\zip\SevenZipSharp.dll"
$pathTo7zDll = "C:\zipz.dll"
$dllByteArray= [System.IO.File]::ReadAllBytes($pathToDll)
[System.Reflection.Assembly]::Load($dllByteArray)

然而,当我想像这样使用库 SevenZip.SevenZipExtractor 时,这不会引发异常:

[SevenZip.SevenZipExtractor]::SetLibraryPath($pathTo7zDll)

它说:Exception calling "SetLibraryPath" with "1" argument(s): "The type initializer for 'SevenZip.SevenZipLibraryManager' threw an exception."

但是,如果我将 [System.Reflection.Assembly]::Load($dllByteArray) 替换为

Add-Type -path $pathToDll

它工作正常。

如果我从字节数组加载程序集,为什么会抛出异常?

编辑: 我想使用字节数组加载它的原因是因为如果我使用 Add-Type 它似乎保留了 .dll 的句柄并且我以后无法使用 Remove-Item 删除它。

编辑: 这有效:

[System.Configuration.ConfigurationManager]::AppSettings["7zLocation"] = $pathToDll

调用前需要先调用[SevenZip.SevenZipExtractor]::SetLibraryPath($pathTo7zDll)

我相信您 运行 遇到了 .NET 的基本限制。一旦程序集加载到您的应用程序域中,就不会卸载该 dll。您需要使用程序集中的类型还是仅对其进行反思?如果是后者,可以把DLL加载到一个reflection-only context.

库正在使用反射通过 Assembly.GetExecutingAssembly().Location 找到自己的路径,并用这个值初始化一些静态字段。 See the source code:

private static string _libraryFileName = ConfigurationManager.AppSettings["7zLocation"] ??
        Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "7z.dll");

但是,如果直接从字节数组加载程序集,Location 为空,GetDirectoryName 将抛出异常。这不是 PowerShell 的限制,而是库的问题。

可能有一个解决方法,即加载 System.Configuration 并在尝试加载库之前设置 7zLocation 应用设置。

由于库似乎试图让您通过 SetLibraryPath 设置路径,这可能是一个错误,应报告给维护者。