制作供C++程序调用的C# DLL时遇程序集加载异常求助
解决CLR包装器调用C# DLL时的System.IO.FileNotFoundException问题
问题背景
编写C#类库SimpleMathLib编译为DLL,通过CLR C静态库做包装器,再用C控制台程序调用。无论使用链接器还是手动加载DLL,运行时均抛出System.IO.FileNotFoundException,提示找不到netstandard等程序集。已安装对应.NET Runtime和SDK,更换目标框架版本仅改变缺失的程序集名称/版本,问题依旧。
解决方案
1. 同步程序集输出目录
- 将
SimpleMathLib.dll及其依赖的所有.NET程序集(如netstandard.dll、System.Runtime.dll等)复制到C++控制台程序的Debug/Release输出目录。 - 若C#类库目标为.NET Core/.NET 5+,可通过
dotnet publish打包所有依赖:
将publish目录下的所有文件复制到C++程序输出目录。dotnet publish SimpleMathLib.csproj -c Release -r win-x64 --self-contained false
2. 匹配CLR目标框架版本
- 右键C++包装器项目 → 属性 → 常规 → 确保公共语言运行时支持版本与C#类库目标框架一致:
- C#用.NET Framework 4.x时,C++选对应
.NET Framework 4.x; - C#用.NET 6/7/8时,C++选对应
.NET Core版本(需安装Visual Studio的.NET Core开发工具)。
- C#用.NET Framework 4.x时,C++选对应
- 同步C++控制台项目与包装器项目的运行库设置(如均为
Multi-threaded Debug DLL (/MDd))。
3. 配置程序集绑定重定向(.NET Framework场景)
- 在C++控制台程序输出目录创建
[程序名].exe.config文件,添加绑定重定向规则:
替换<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="netstandard" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.3.0" newVersion="2.0.3.0" /> <codeBase version="2.0.3.0" href="netstandard.dll" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>publicKeyToken和版本号为实际缺失程序集的信息。
4. 手动加载程序集的正确方式
- 若手动加载C# DLL,需先设置程序集解析路径:
在加载C# DLL前调用#include <mscoree.h> #pragma comment(lib, "mscoree.lib") void SetAssemblySearchPath(const wchar_t* path) { ICLRMetaHost* pMetaHost = nullptr; ICLRRuntimeInfo* pRuntimeInfo = nullptr; ICLRRuntimeHost* pRuntimeHost = nullptr; if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost) == S_OK) { pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo); pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pRuntimeHost); pRuntimeHost->Start(); ICLRControl* pControl = nullptr; pRuntimeHost->GetCLRControl(&pControl); ICLRAssemblyIdentityManager* pIdentityManager = nullptr; pControl->GetCLRManager(IID_ICLRAssemblyIdentityManager, (LPVOID*)&pIdentityManager); ICLRAssemblyReferenceList* pRefList = nullptr; pIdentityManager->CreateAssemblyReferenceListFromPath(path, &pRefList); pControl->SetAppDomainManagerType(L"", L"", pRefList); pRefList->Release(); pIdentityManager->Release(); pControl->Release(); pRuntimeHost->Release(); pRuntimeInfo->Release(); pMetaHost->Release(); } }SetAssemblySearchPath传入C# DLL所在目录。
5. 配置项目部署规则
- 右键C++控制台项目 → 属性 → 部署 → 将C# DLL及其依赖项添加为附加文件,设置复制到输出目录为始终复制。
内容的提问来源于stack exchange,提问作者Apache81
相关产品推荐
相关产品推荐

