C#/WinRT 是 NuGet 打包的工具包,它为 C# 语言提供Windows Runtime(WinRT)投影支持。 投影程序集是一个互作程序集,它使 WinRT API 能够以自然且熟悉的方式对目标语言进行编程。 C#/WinRT 投影隐藏了 C# 和 WinRT 接口之间互操作的详细信息,并提供许多 WinRT 类型 到适当 .NET 等效项的映射,如字符串、URI、常见值类型和泛型集合。
C#/WinRT 当前通过 .NET 中使用 Target Framework 标识符(TFM)来支持使用 WinRT API 接口。 使用特定 Windows SDK 版本设置 TFM 将添加对 C#/WinRT 所生成的 Windows SDK 投影和运行时程序集的引用。
使用 C#/WinRT NuGet 包可为 .NET 用户创建和 引用自己的 WinRT 互操作程序集。 最新的 C#/WinRT 版本还包括在 C# 中编写 WinRT 类型的 预览版。
有关详细信息,请参阅 C#/WinRT GitHub 存储库。
C#/WinRT 的动机
.NET(以前称为.NET核心)是一种开源的跨平台运行时,可用于生成设备、云和 IoT 应用程序。
以前版本的 .NET Framework 和 .NET Core 对 WinRT(特定于 Windows 的技术)具有内置知识。 为了支持 .NET 6+ 的可移植性和效率目标,我们从 .NET 编译器和运行时中解除了 WinRT 投影支持,并将其移动到 C#/WinRT 工具包(请参阅 WinRT 的内置支持已从 .NET 中删除)。 C#/WinRT 的目标是与早期版本的 C# 编译器和.NET 运行时提供的内置 WinRT 支持保持一致。 有关详细信息,请参阅Windows Runtime 类型的 .NET 映射。
C#/WinRT 还支持 Windows App SDK 中的组件,包括 WinUI 3。 Windows App SDK将本机Microsoft UI控件和其他本机组件从操作系统中剥离出来。 这使应用开发人员能够在 Windows 10 版本 1809 及更高版本上使用最新的控件和组件。
最后,C#/WinRT 是一个常规工具包,旨在支持在 C# 编译器或.NET运行时中不提供对 WinRT 的内置支持的其他方案。
新动态
可在 Github 存储库中的 release notes 页上找到最新的 C#/WinRT 版本。
使用情况
C#/WinRT NuGet 包可用于生成从 WinRT 组件到 C# 投影(也称为互操作程序集),以及在编写 C#/WinRT 组件。 有关 C#/WinRT 的使用方案的更多详细信息,请参阅存储库上的 usage 指南。
生成和分发互操作程序集
WinRT API 在 Windows 元数据 (WinMD) 文件中定义。 C#/WinRT NuGet 包(Microsoft.Windows.CsWinRT) 包括 C#/WinRT 编译器cswinrt.exe,可用于处理 WinMD 文件和生成 .NET C# 代码。 C#/WinRT 将这些源文件编译为互作程序集,类似于 C++/WinRT 如何为 C++ 语言投影生成标头。 然后,可以分发 C#/WinRT 互操作程序集以及 .NET 应用程序引用的实现程序集,通常作为 NuGet 包进行分发。
有关如何生成和分发互作程序集的更多详细信息,请参阅从 C++/WinRT 组件生成 C# 投影,以 nuGet 的形式分发为 .NET 应用。
引用互操作程序集
通常,C#/WinRT 互作程序集由应用程序项目引用。 但是,中间互作程序集也可能反过来引用它们。 例如,WinUI 互作程序集将引用 Windows SDK 互作程序集。
如果在没有官方互作程序集的情况下分发第三方 WinRT 组件,则应用程序project可能遵循 生成互作程序集以生成其自己的专用投影源的过程。 不建议使用此方法,因为它可以在进程中生成同一类型的冲突投影。 NuGet 打包遵循 语义版本控制 方案,旨在防止这种情况。 首选官方的第三方互操作程序集。
对 WinRT 类型的嵌入式支持(预览版)
从 C#/WinRT 版本 1.4.1 开始,支持将 .NET 和 .NET Standard 2.0 的 Windows SDK 投影和运行时源嵌入到库或应用的输出中。 在使用 Windows SDK 类型是自包含的情况下,这非常有用。 嵌入式支持会删除 WinRT.Runtime.dll 和 Microsoft.Windows.SDK 上的依赖项.NET.dll从而减少库或应用输出大小。 它还允许库开发人员提供下层支持,并消除了对多目标的需求。
有关详细信息,请参阅存储库上的 C#/WinRT 嵌入式文档。
WinRT 类型激活
C#/WinRT 支持激活由作系统托管的 WinRT 类型,以及 Win2D 等第三方组件。 支持桌面应用程序中第三方组件的激活已通过无注册的 WinRT 激活功能启用(请参阅 使用 Windows 运行时组件增强非打包桌面应用),适用于 Windows 10 版本 1903 及更高版本。 本机 C++ 组件应在项目属性或 文件中将 Windows Desktop Compatible 属性设置为 .vcxproj,以便引用和转发 Microsoft.VCLibs.Desktop 二进制文件到相关的应用程序。 否则,如果组件仅面向 UWP 应用,则消费应用需要 VCRT 转发器 包。
如果 Windows 无法激活类型,C#/WinRT 还提供激活回退路径,如上文所述。 在这种情况下,C#/WinRT 会尝试根据完全限定的类型名称查找本机实现 DLL,逐渐删除元素。 例如,回退逻辑会尝试按顺序从以下模块激活 Contoso.Controls.Widget 类型:
- Contoso.Controls.Widget.dll
- Contoso.Controls.dll
- Contoso.dll
C#/WinRT 使用 LoadLibrary 备用搜索顺序 查找实现 DLL。 依赖于此回退行为的应用应将实现 DLL 与应用模块一起打包。
常见错误和故障排除
错误:“未提供或检测到 Windows 元数据。
可以使用
<CsWinRTWindowsMetadata>project 属性指定 Windows 元数据,例如:<CsWinRTWindowsMetadata>10.0.19041.0</CsWinRTWindowsMetadata>在 C#/WinRT 版本 1.2.1 及更高版本中,此属性默认值为
TargetPlatformVersion,它派生自在TargetFramework属性中指定的 Windows SDK 版本。错误 CS0246:找不到类型或命名空间名称“Windows”(是否缺少 using 指令或程序集引用?)
若要解决此错误,请编辑属性
<TargetFramework>以面向特定 Windows 版本,例如:<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>-
将对象强制转换为带有
ComImport属性的接口时,需要使用.As<>运算符,而非显式使用强制转换表达式。 例如:someObject.As<SomeComImportInterface>有关详细信息,请参阅 COM 互作指南。
System.Runtime.InteropServices.COMException:未注册的类(0x80040154(REGDB_E_CLASSNOTREG))
- 如果在使用 C++/WinRT 组件消费 C#/WinRT 投影时看到此异常,请确保组件已通过项目属性或
.vcxproj文件将 Windows Desktop Compatible 属性设置为 True。
- 如果在使用 C++/WinRT 组件消费 C#/WinRT 投影时看到此异常,请确保组件已通过项目属性或
.NET SDK 版本控制错误
在使用比其任何依赖项版本更早的 .NET SDK 版本生成的项目中,您可能会遇到以下错误或警告。
| 错误或警告消息 | 原因 |
|---|---|
| 警告 MSB3277:发现无法解决的 WinRT.Runtime 或 Microsoft.Windows.SDK.NET 的不同版本之间的冲突。 | 引用一个在其 API 表面公开 Windows SDK 类型的库时,会出现此构建警告。 |
| 错误 CS1705:程序集“AssemblyName1”使用版本高于引用的程序集“AssemblyName2”的“TypeName” | 引用和使用库中公开的 Windows SDK 类型时,会发生此生成编译器错误。 |
| System.IO.FileLoadException | 在未公开 Windows SDK 类型的库中调用某些 API 时,可能会出现此运行时错误。 |
若要修复这些错误,请将 .NET SDK 更新到最新版本。 这样做可确保应用程序使用的运行时和 Windows SDK 程序集版本与所有依赖项兼容。 这些错误可能与.NET SDK 的早期维护/功能更新一起发生,因为运行时修复可能需要更新程序集版本。
已知问题
C#/WinRT GitHub 存储库中记录了已知问题和重大变更。
如果遇到 C#/WinRT NuGet 包、cswinrt.exe 编译器或生成的投影源的任何功能问题,请通过 C#/WinRT 问题页提交问题。