.NET 5 TFM环境下调用ICompositorDesktopInterop抛出异常问题咨询
根因分析
.NET 5 及更高版本重构了WinRT类型的互操作机制,移除了对自定义[ComImport]标记的InterfaceIsIInspectable类型的手动封送支持,你遇到的异常就是这个改动导致的。
在.NET Framework 4.8 中,Microsoft.Windows.SDK.Contracts包自带了完整的WinRT类型投影,支持你自定义的IInspectable接口封送逻辑。但.NET 5改用Target Framework Monikers (TFMs) 内置WinRT支持后,这套自定义封送逻辑被废弃,只有SDK自带的投影类型才能被正常封送。
缺失的适配操作
你需要做以下调整解决问题:
- 修正项目TFM配置
首先修改项目文件的目标框架配置,使用带Windows版本后缀的TFM,开启内置WinRT支持,同时指定具体平台架构(WinRT API不支持AnyCPU),示例配置如下:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <!-- 可根据你需要兼容的最低Windows版本调整版本号,最低不低于10.0.17134.0 --> <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework> <UseWinRT>true</UseWinRT> <Platforms>x64;x86</Platforms> </PropertyGroup> </Project> - 清理冲突依赖和冗余代码
- 卸载项目中所有
Microsoft.Windows.SDK.Contracts相关的NuGet包,避免和内置WinRT支持产生类型冲突 - 删除你手动定义的
ICompositorDesktopInterop、ICompositionTarget两个[ComImport]接口代码,TFM内置的Windows SDK投影已经包含对应的类型定义,不需要手动声明
- 卸载项目中所有
- 调整互操作代码
原来Microsoft.Windows.SDK.Contracts包提供的As<T>扩展方法不再可用,改用WinRT内置的封送方法获取互操作接口,修改后的代码如下:private ICompositionTarget compositionTarget; public Compositor compositor; private void InitComposition(IntPtr hwnd) { compositor = new Compositor(); // 用内置方法获取桌面互操作接口 var interop = WinRT.MarshalInspectable.As<Compositor, ICompositorDesktopInterop>(compositor); interop.CreateDesktopWindowTarget(hwnd, true, out compositionTarget); compositionTarget.Root = compositor.CreateSpriteVisual(); }
额外注意事项
如果按照以上配置还是报错,可以安装Microsoft.Windows.CsWin32NuGet包,通过该工具自动生成所需的COM接口定义,完全避免手动写ComImport代码可能出现的GUID、接口类型标记错误问题。
内容的提问来源于stack exchange,提问作者Selastin
相关产品推荐
相关产品推荐

