C++/WinRT调用返回IAsyncOperation/IList的C#/WinRT组件时类未注册
解决方案
1. 修正应用程序清单配置
你的清单文件存在核心错误:WinRT.Host.dll并非托管WinRT组件的正确宿主入口,需将你的C#组件DLL(如csharp_winrt.dll)作为<file>元素的目标,同时确保activatableClass的命名空间和类名完全匹配:
<?xml version="1.0" encoding="utf-8"?> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyIdentity version="1.0.0.0" name="sdk_demo.exe"/> <!-- 替换为你的C#组件DLL文件名 --> <file name="csharp_winrt.dll"> <activatableClass name="csharp_winrt.CSharpWinrtInterface" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" /> </file> <!-- 若依赖WinRT.Runtime.dll,需添加此条目 --> <file name="WinRT.Runtime.dll" /> </assembly>
2. 确保C#项目的CsWinRT配置完整
检查C#项目的.csproj文件,确认以下配置项正确:
- 目标框架必须为Windows SDK兼容版本(如
net6.0-windows10.0.19041.0或更高) - 启用CsWinRT组件并指定输出路径:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework> <CsWinRTComponent>true</CsWinRTComponent> <!-- 输出到C++项目可访问的路径 --> <OutputPath>..\cpp_winrt_project\output\</OutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.0" /> </ItemGroup> </Project>
3. 验证C++项目的依赖复制
确保C++项目输出目录包含以下文件:
- 你的C#组件DLL(
csharp_winrt.dll) WinRT.Runtime.dll(CsWinRT核心运行时)- 生成的
.winmd文件(csharp_winrt.winmd)
可通过添加生成后事件自动复制:
xcopy /Y "$(SolutionDir)csharp_winrt\bin\$(Configuration)\net6.0-windows10.0.19041.0\*.dll" "$(OutDir)" xcopy /Y "$(SolutionDir)csharp_winrt\bin\$(Configuration)\net6.0-windows10.0.19041.0\*.winmd" "$(OutDir)"
4. 修正C++调用代码的拼写与输出逻辑
你的C++代码存在变量名拼写错误,且WinRT字符串需用宽字符输出:
#include "winrt/csharp_winrt.h" #include <winrt/Windows.Foundations.h> #include <iostream> void testCSharpCall() { winrt::csharp_winrt::CSharpWinrtInterface csharp_winrt_interface; auto result = co_await csharp_winrt_interface.HelloAsync(); // 修正拼写错误 std::wcout << result.c_str() << std::endl; // 使用std::wcout输出宽字符 }
5. 优化异步方法实现(可选)
无需用Task.Run包装,直接使用AsyncInfo.Run更符合WinRT规范:
using Windows.Foundation; using System.Threading.Tasks; namespace csharp_winrt { public sealed class CSharpWinrtInterface { public IAsyncOperation<string> HelloAsync() { return AsyncInfo.Run(async token => { await Task.Delay(2000, token); return "Hello World!"; }); } } }
关键原因分析
当方法返回IAsyncOperation<T>等复杂WinRT类型时,WinRT需要完整的组件注册信息来加载托管运行时宿主;错误的清单配置会导致系统无法定位activatable类,从而抛出REGDB_E_CLASSNOTREG。而返回简单类型时,WinRT的类型解析逻辑更简化,因此可正常运行。
内容的提问来源于stack exchange,提问作者Vanilson Nogueira
相关产品推荐
相关产品推荐

