从原生Win32应用调用含Roslyn引用的.NET DLL加载失败求助
解决原生Win32通过C++/CLR调用依赖Roslyn的.NET5 DLL的程序集加载问题
针对你遇到的System.IO.FileNotFoundException(无法加载Microsoft.CodeAnalysis系列程序集)问题,核心原因是原生Win32 EXE作为CLR宿主时,默认的程序集探测路径仅指向原生EXE所在目录,而Roslyn的依赖未被CLR正确识别。以下是具体解决方案:
1. 在C++/CLR桥接层手动配置程序集探测路径
在CLRLibCaller的初始化逻辑中,强制将DynCodeDll所在目录添加到CLR的私有程序集搜索路径,同时注册AssemblyResolve事件作为兜底,确保所有依赖能被正确加载:
#using <System.dll> #using <System.IO.dll> using namespace System; using namespace System::Reflection; using namespace System::IO; void InitAssemblySearchPath() { // 加载DynCodeDll并获取其所在目录 Assembly^ dynCodeAssembly = Assembly::LoadFrom(L"DynCodeDll.dll"); String^ dynCodeDir = Path::GetDirectoryName(dynCodeAssembly->Location); // 设置CLR私有程序集搜索路径 AppDomain::CurrentDomain->PrivateBinPath = dynCodeDir; // 注册AssemblyResolve事件,兜底加载未找到的依赖 AppDomain::CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler( [dynCodeDir](Object^ sender, ResolveEventArgs^ args) -> Assembly^ { String^ assemblyShortName = gcnew AssemblyName(args->Name)->Name; String^ assemblyPath = Path::Combine(dynCodeDir, assemblyShortName + L".dll"); if (File::Exists(assemblyPath)) { return Assembly::LoadFrom(assemblyPath); } return nullptr; } ); }
注意:必须在调用DynCodeDll的任何功能之前调用InitAssemblySearchPath函数。
2. 正确部署DynCodeDll的所有依赖
使用.NET5的dotnet publish命令发布DynCodeDll,确保所有Roslyn相关依赖(如Microsoft.CodeAnalysis.CSharp.dll、Microsoft.CodeAnalysis.dll等)被完整导出:
dotnet publish DynCodeDll.csproj -c Release -f net5.0 --self-contained false
将发布目录下的所有文件(包括DynCodeDll.dll、runtimeconfig.json及所有依赖DLL)复制到NativeExeCaller的输出目录,或者在InitAssemblySearchPath中指定该发布目录为搜索路径。
3. 检查C++/CLR项目的配置兼容性
- 确保
CLRLibCaller项目的公共语言运行时支持设置为/clr:netcore(项目属性→配置属性→C/C++→所有选项→公共语言运行时支持),目标.NET版本与DynCodeDll一致(.NET5)。 - 确认
CLRLibCaller的输出目录与NativeExeCaller的输出目录一致,或通过项目依赖设置自动复制CLRLibCaller到原生EXE目录。
4. 利用AssemblyLoadContext精准加载依赖
如果上述方法仍有问题,可使用AssemblyLoadContext加载DynCodeDll,指定其依赖目录和配置文件:
#using <System.Runtime.Loader.dll> using namespace System::Runtime::Loader; Assembly^ LoadDynCodeDll() { String^ dynCodeDir = L"[DynCodeDll的发布目录路径]"; String^ configPath = Path::Combine(dynCodeDir, L"DynCodeDll.runtimeconfig.json"); AssemblyLoadContext^ alc = AssemblyLoadContext::LoadFromAssemblyPath( Path::Combine(dynCodeDir, L"DynCodeDll.dll"), configPath ); return alc->LoadFromAssemblyName(gcnew AssemblyName(L"DynCodeDll")); }
内容的提问来源于stack exchange,提问作者suriel
相关产品推荐
相关产品推荐

