通过AppDomain的AssemblyResolve事件在PowerShell中加载程序集失败问题
解决AssemblyResolve事件动态加载DLL失败及StackOverflow异常问题
问题根源分析
你的脚本存在两个核心问题:
- 变量拼写错误:在过滤System.Management.Automation相关程序集时,错误使用了
$e.assemblyName(正确应为$assemblyName),导致过滤逻辑完全失效,无法阻止系统反复尝试加载资源程序集,最终触发StackOverflow异常。 - 无差别加载目标DLL:当前事件处理逻辑对所有程序集请求都返回TestAssembly.dll,无论请求的是目标程序集还是其他系统程序集,这种错误匹配会引发循环解析,导致类型加载失败。
修正后的脚本
Set-StrictMode -Version Latest # Step 1: 定义AssemblyResolve事件处理程序 $AssemblyResolveHandler = [ResolveEventHandler] { param( [Object]$sender, [ResolveEventArgs]$e ) # 提取不带版本、区域和公钥的程序集名称 $assemblyName = $e.Name.Split(',')[0] Write-Host "正在解析程序集: $assemblyName" # 过滤系统程序集,让CLR自行处理 if ($assemblyName -like "System.Management.Automation*") { return $null } # 仅当请求的是目标程序集时,才加载对应的DLL if ($assemblyName -eq "TestAssembly") { $assemblyPath = Join-Path -Path $env:TEMP -ChildPath "TestAssembly.dll" if (Test-Path $assemblyPath) { return [Reflection.Assembly]::LoadFrom($assemblyPath) } } return $null } # Step 2: 注册事件处理程序 [AppDomain]::CurrentDomain.add_AssemblyResolve($assemblyResolveHandler) Write-Host "*** AssemblyResolve事件处理程序已注册 ***" # Step 3: 尝试调用目标静态方法 try { [Test.QuoteServer]::GetQuote() } catch { Write-Warning "加载类型失败,错误信息: $_" } # 直接加载验证(可选) $assemblyPath = Join-Path -Path $env:TEMP -ChildPath "TestAssembly.dll" try { Add-Type -Path $assemblyPath $result = [Test.QuoteServer]::GetQuote() Write-Host "直接加载调用结果: $result" } catch { Write-Warning "直接加载失败,LoaderExceptions: $_" }
关键修正点说明
- 修复变量拼写:将过滤条件中的
$e.assemblyName改为$assemblyName,确保系统程序集过滤生效,避免循环解析。 - 精准匹配目标程序集:只有当请求的程序集名称是
TestAssembly时,才加载对应的DLL,其他请求交给CLR默认的解析逻辑处理,避免错误加载无关程序集。 - 保留日志输出:保留
Write-Host输出,方便调试时查看当前解析的程序集名称,快速定位问题。
内容的提问来源于stack exchange,提问作者Peter M.
相关产品推荐
相关产品推荐

