-2

这个LoadFile()功能真的让我很难过。我有两个程序集 ,Asm1.dll并且Asm2.dll正在 GAC 中安装。稍后,这些程序集被加载LoadFile()用于创建匹配的类型库。

这一切都适用于Asm1.dll(在 PowerShell 中测试):

[System.Reflection.Assembly]::LoadFile("D:\MyTools\Asm1.dll")

GAC    Version        Location
True   v4.0.30319     C:\Windows\Microsoft.Net\assembly\GAC_64\Asm1\v4.0_4.0.30000.0__abcdef123456\Asm1.dll

但它不适合Asm2.dll

[System.Reflection.Assembly]::LoadFile("D:\MyTools\Asm2.dll")

Exception calling "LoadFile" with "1" argument(s): "Could not load file or assembly 'Asm2.dll'
or one of its dependencies. The specified module could not be found."

但是,这两个程序集确实存在于我的工作文件夹以及 GAC 中:

gci C:\Windows\Microsoft.Net\assembly\GAC_64\Asm2\v4.0_2.3.30000.0__abcdef123456\Asm2.dll
gci C:\Windows\Microsoft.Net\assembly\GAC_64\Asm1\v4.0_4.0.30000.0__abcdef123456\Asm1.dll

Mode                LastWriteTime         Length Name
-a----      10 Mar 2021     15:37        1494528 Asm2.dll
-a----      10 Mar 2021     12:47        6749184 Asm1.dll

gci D:\MyTools\Asm1.dll
gci D:\MyTools\Asm2.dll

Mode                LastWriteTime         Length Name
-a----      10 Mar 2021     12:47        6749184 Asm1.dll
-a----      10 Mar 2021     14:00        1494528 Asm2.dll

我还尝试LoadFile()了完整的 GAC 路径——两个程序集的结果相同。

从过去我知道,在重建我的工具之前,从我的组件的所有痕迹中清除 HKCU 注册表和 GAC 后,问题就消失了。但在我更新了 Visual Studio 并在没有先清理所有内容的情况下重建了我的工具之后,它确实在今天早上重新出现。

LoadFile()函数就像一个黑匣子,给我关于哪里出了问题的完全信息。形象地说,我不想再通过“当我只是在寻找熔断的保险丝时拆除我的整个建筑物”来解决这个问题。

那么我如何才能跟踪此失败的根本原因呢?

编辑

@Efie 谢谢。$error[0]唯一指向LoadFile()函数作为错误源。那里没有其他见解。

@Ian Kemp,@Jeroen Mostert 感谢您推荐融合日志查看器。

它确实提供了一些信息,但仍未指出实际原因。相反 - 日志表明程序集绑定成功,而错误消息仍然出现在 PowerShell 控制台中。

The operation was successful.

=== Pre-bind state information ===
LOG: DisplayName = Asm2, Version=2.3.30000.0, Culture=neutral, 
PublicKeyToken=abcdef123456
 (Fully-specified)
LOG: Appbase = file:///C:/Windows/system32/WindowsPowerShell/v1.0/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = PowerShell_ISE.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: 
C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from 
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Binding succeeds. Returns assembly from C:\Windows\Microsoft.Net\assembly\GAC_64\Asm2\v4.0_2.3.30000.0__abcdef123456\Asm2.dll.
LOG: Assembly is loaded in default load context.

两个程序集的日志文件除了名称、版本和融合日志明确报告它在 GAC 中找到的事实之外是相同的,Asm1没有这样做:Asm2Asm1Asm2

LOG: Post-policy reference: Asm1, Version=4.0.30000.0, Culture=neutral, PublicKeyToken=abcdef123456
LOG: Found assembly by looking in the GAC.

如果我在两个调用中指定完整的 GAC 路径,则两个程序集的日志文件除了名称和版本之外是相同Asm1的;包括 - 行。Asm2LoadFile()Post-policy

4

1 回答 1

0

我过去使用的模式是这样的(我是从记忆中做的,所以可能需要调整才能真正起作用!):

try
{
    Add-Type -LiteralPath "c:\temp\myassembly.dll";
}
catch [System.Reflection.ReflectionTypeLoadException]
{
    $ex = $_.psbase.Exception;
    foreach( $item in $ex.LoaderExceptions )
    {
        write-host $ex.ToString();
    }
    throw;
}
于 2021-03-10T15:55:51.097 回答