.NET 6类库间接调用时无法加载同目录.NET Standard版NuGet包异常
问题背景
我共维护70个.NET 6项目,其中6个项目长期使用同一款面向.NET Standard的NuGet包实现XML文件读取功能,数月前完成所有项目到.NET 6的升级后系统运行正常。近期其中一个C#类库在构造函数执行时抛出程序集加载异常,错误提示如下:
.ctor Could not load file or assembly xxx blah blah. The system could not find the file specified.
经确认,报错提示无法找到的NuGet包实际存放在应用程序的文件系统加载目录中,与调用该包的DLL位于同一路径。
构建执行情况
我使用如下MSBuild参数执行构建发布流程,构建全程无警告、无错误:
Deleting hscore\hscore\bin Deleting hscore\hscore\obj Deleting
hscore\hscore\packages "C:\Program Files\Microsoft Visual
Studio\2022\Community\MSBuild\Current\Bin\msbuild.exe" -nologo -m
-V:minimal -t:clean;restore;publish /p:Platform=AnyCPU /p:PlatformTarget=AnyCPU /p:Configuration=Debug
/p:TargetFramework=net6.0-windows7.0 /p:RuntimeIdentifier=win-x64
/p:SelfContained=false /p:PublishProtcol=FileSystem
/p:DeleteExistingFiles=true /p:PublishDir=c:\dev\holding\core.plt
-nowarn:MSB3305 c:\dev\products\hscore\hscore\hscore.csprojDetermining projects to restore... Restored
c:\dev\products\hscore\hscore\hscore.csproj (in 874 ms).
hscore -> c:\dev\products\hscore\hscore\bin\Debug\net6.0-windows7.0\win-x64\hscore.dll
hscore -> c:\dev\holding\core.plt\
已完成基础排查(均未解决问题)
- 删除报错类库的bin、obj文件夹后重新生成
- 核对所有项目目标框架均为
net6.0-windows7.0 - 核对所有项目运行时标识符(RuntimeIdentifier)均为
win-x64 - 核对生成配置为Debug、平台目标为AnyCPU
- 移除后重新添加指定版本的NuGet包
- 确认该NuGet包面向.NET Standard,与.NET 6兼容
- 其他.NET 6项目引用同版本NuGet包运行正常
- 执行包还原、DLL重建操作
- 将生成产物发布到程序实际运行的目标目录
- 确认目标目录中确实存在对应的NuGet包文件
- 尝试使用SysInternals Process Monitor追踪进程的DLL加载行为,因操作不熟练未定位到程序集搜索路径相关问题
最初怀疑问题根源是.NET 5/.NET 6与目录中NuGet包版本不匹配(此前曾遇到.NET Framework版本NuGet包无法被.NET 5程序集加载的问题),但目前所有项目均已升级为.NET 6,不存在.NET Framework项目,可排除该原因。近期仅调整过构建系统与构建参数,批处理构建与并行构建使用完全相同的MSBuild参数,构建发布全程无异常。该NuGet包会自动拉取10-20个依赖项,其他控制台程序、应用在同目录下引用该NuGet包均可正常运行,可排除NuGet包本身故障;且报错的类库已有数月未修改代码,此前一直运行正常。
补充排查结果
- 将无法加载的NuGet包升级到最新版本,同步替换70个项目中的包引用后全量重建,仍出现新版本包无法找到的异常;Visual Studio中相关代码的单元测试全部运行正常(VS可正常加载该NuGet包)
- 安装
dotnet-trace工具追踪DLL加载行为,可见程序加载各类应用DLL、系统DLL的路径记录,但未查询到目标NuGet包的有效加载记录;追踪日志显示系统依次经过FindInLoadContext、ApplicationAssemblies、AppDomainAssemblyResolveEvent三个阶段搜索程序集,最终因未找到包抛出异常,未在执行程序集、请求程序集所在的同目录下搜索到目标包 - 复现场景确认:异常触发链路为WindowsFormsApp加载
MyCore.dll,调用new MyCore.MyObject()时,构造函数通过MyUtils.dll读取XML文件,MyUtils.dll尝试引用目标NuGet包时加载失败;编写小型控制台程序直接加载MyUtils.dll,调用相同的MyUtils.ReadMyXmlFiles接口,在相同目录下可正常加载NuGet包、完成XML文件读取
目前仅在WinForm应用通过中间层DLL、构造函数间接调用MyUtils.dll时出现加载失败,怀疑该调用场景修改了Assembly Load Context(即FindInLoadContext阶段的搜索规则),现咨询可行的问题排查与解决方案。
内容的提问来源于stack exchange,提问作者Kevin

