.Net6下C++/CLI项目打包Nuget安装后报FileNotFoundException错误
问题根因
.NET 6(.NET Core 3.0及以上版本)对C++/CLI混合模式程序集(同时包含IL代码和原生C++代码)的NuGet包结构、加载规则和.NET Framework完全不同,你的打包方式存在三个核心错误:
- 目标框架标识(TFM)写法错误:不存在
netcoreapp6.0这个官方TFM,.NET 5及以上版本的统一TFM格式为netX.0,且C++/CLI程序集仅支持Windows平台,需使用net6.0-windows作为目标框架标识。 - 程序集存放路径错误:.NET Core/.NET 5+规则下,带原生代码的混合程序集不能直接放在
lib目录下,必须放入runtimes目录下对应系统、架构的子文件夹,同时需要补充构建时的props/targets文件声明包的架构相关属性,否则MSBuild和运行时会将其识别为纯IL跨平台程序集,哪怕dll被复制到输出目录,加载原生层时也会失败抛出文件找不到异常。 - 缺少架构匹配逻辑:C++/CLI程序集是架构强相关的(x86/x64/arm64版本不通用),直接放在lib目录下不会触发架构校验,引用项目如果用AnyCPU配置、或架构和C++/CLI dll不匹配,就会加载失败。
直接项目引用能正常运行,是因为MSBuild可以直接读取C++/CLI项目的配置属性,自动处理架构匹配、文件复制和加载逻辑,不需要额外的元数据声明。
修复方案
1. 修正MyClrLib的nuspec配置
将原有MyClrLib.nuspec替换为以下内容,如果你只需要支持单一架构,可以删除不需要的架构节点:
<?xml version="1.0"?> <package > <metadata> <id>MyClrLib</id> <version>1.0.2</version> <title>MyClrLib</title> <authors>Me</authors> <description>My CLR Lib.</description> <releaseNotes>First release</releaseNotes> <copyright>Copyright 2022</copyright> <platforms>Windows</platforms> <dependencies> <group targetFramework="net6.0-windows" /> </dependencies> </metadata> <files> <!-- x86版本dll,替换为你实际的x86编译输出路径 --> <file src="..\Win32\$configuration$\MyClrLib.dll" target="runtimes\win-x86\native\MyClrLib.dll"/> <!-- x64版本dll,替换为你实际的x64编译输出路径 --> <file src="..\x64\$configuration$\MyClrLib.dll" target="runtimes\win-x64\native\MyClrLib.dll"/> <!-- 构建规则文件 --> <file src="build\MyClrLib.props" target="build\net6.0-windows\MyClrLib.props"/> <file src="build\MyClrLib.targets" target="build\net6.0-windows\MyClrLib.targets"/> </files> </package>
2. 添加构建规则文件
在MyClrLib.nuspec同级目录新建build文件夹,在其中创建两个配置文件:
第一个是MyClrLib.props,作用是标记当前包为架构相关组件,禁止AnyCPU编译:
<Project> <PropertyGroup> <_HasPlatformSpecificAssets>true</_HasPlatformSpecificAssets> </PropertyGroup> </Project>
第二个是MyClrLib.targets,作用是根据引用项目的目标架构,匹配对应版本的C++/CLI dll:
<Project> <ItemGroup Condition="'$(PlatformTarget)' == 'x86'"> <Reference Include="MyClrLib"> <HintPath>$(MSBuildThisFileDirectory)..\..\runtimes\win-x86\native\MyClrLib.dll</HintPath> <Private>true</Private> </Reference> </ItemGroup> <ItemGroup Condition="'$(PlatformTarget)' == 'x64'"> <Reference Include="MyClrLib"> <HintPath>$(MSBuildThisFileDirectory)..\..\runtimes\win-x64\native\MyClrLib.dll</HintPath> <Private>true</Private> </Reference> </ItemGroup> </Project>
3. 修正MyNet6Lib的nuspec配置
将原有lib\netcoreapp6.0路径修改为lib\net6.0-windows,同时在metadata的dependencies节点添加对MyClrLib对应版本的依赖声明,避免安装时缺少依赖。
注意事项
- 引用MyClrLib包的C#项目不能使用AnyCPU生成配置,必须明确指定目标平台为x86或x64,和你打包的C++/CLI dll架构匹配。
- 编译C++/CLI项目时,必须确认C++项目的编译选项为
/clr:netcore,目标框架设置为.NET 6,不能使用.NET Framework版本的/clr选项编译。 - C++/CLI项目依赖的所有原生dll(包括封装的原生C类库、VC CRT运行库等),都需要和MyClrLib.dll一起放到对应架构的runtimes目录下,否则也会触发文件找不到异常。
排查方向
如果修改后仍有异常,可以按以下步骤定位问题:
- 使用程序集绑定日志查看器(fuslogvw.exe)抓取MyClrLib的详细加载日志,确认失败原因是文件缺失、架构不匹配还是依赖缺失。
- 检查C#项目生成输出目录下的
runtimes子文件夹,确认对应架构的MyClrLib.dll和其依赖的原生dll是否被正确复制。 - 检查C#项目的生成配置,确认平台目标和C++/CLI dll的架构一致,没有开启AnyCPU优先32位之类的兼容选项。
内容的提问来源于stack exchange,提问作者user5265160
相关产品推荐
相关产品推荐

