C#/WinRT 是 NuGet 打包的工具包,它为 C# 语言提供 Windows 运行时(WinRT)投影支持。 投影程序集是一个互作程序集,它使 WinRT API 能够以自然且熟悉的方式对目标语言进行编程。 C#/WinRT 投影隐藏 C# 和 WinRT 接口之间的交互操作的详细信息,同时提供许多 WinRT 类型到适当的 .NET 等效项的映射,例如字符串、URI、常见值类型和泛型集合。
C#/WinRT 目前通过 .NET 中使用 目标框架名称(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 Core)是一种开源跨平台运行时,可用于生成设备、云和 IoT 应用程序。
以前版本的 .NET Framework 和 .NET Core 对 WinRT 有内置知识,这是一种特定于 Windows 的技术。 为了支持 .NET 6+ 的可移植性和效率目标,我们从 .NET 编译器和运行时中解除了 WinRT 投影支持,并将其移动到 C#/WinRT 工具包(请参阅 WinRT 的内置支持已从 .NET 中删除)。 C#/WinRT 的目标是与早期版本的 C# 编译器和 .NET 运行时提供的内置 WinRT 支持实现功能对等。 有关详细信息,请参阅 Windows 运行时类型的 .NET 映射。
C#/WinRT 还支持 Windows 应用 SDK 中的组件,包括 WinUI。 Windows 应用 SDK 将本机 Microsoft UI 控件和其他本机组件从操作系统中提升出来。 这使应用开发人员能够在 Windows 10 版本 1809 及更高版本上使用最新的控件和组件。
最后,C#/WinRT 是一个常规工具包,旨在支持在 C# 编译器或 .NET 运行时中不提供对 WinRT 的内置支持的其他方案。
新动态
可以在 Github 存储库的 发行说明 页面上找到最新的 C#/WinRT 版本。
使用情况
C#/WinRT NuGet 包可用于从 WinRT 组件生成 C# 投影(也称为互操作程序集)以及用于创作 C#/WinRT 组件。 有关 C#/WinRT 的使用方案的更多详细信息,请参阅存储库的使用 指南 。
生成和分发互操作程序集
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# 投影,作为 .NET 应用的 NuGet 进行分发。
引用互操作程序集
通常,C#/WinRT 互作程序集由应用程序项目引用。 但是,中间互作程序集也可能反过来引用它们。 例如,WinUI 互作程序集将引用 Windows SDK 互作程序集。
如果在没有官方互作程序集的情况下分发第三方 WinRT 组件,应用程序项目可能会遵循 生成互作程序集 以生成其自己的专用投影源的过程。 不建议使用此方法,因为它可以在进程中生成同一类型的冲突投影。 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 桌面兼容属性设置为 .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 元数据。
可以使用项目属性指定 Windows 元数据
<CsWinRTWindowsMetadata>,例如:<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特性的接口时,出现System.InvalidCastException异常。将对象强制转换为带有
ComImport属性的接口时,需要使用.As<>运算符,而非显式使用强制转换表达式。 例如:someObject.As<SomeComImportInterface>有关详细信息,请参阅 COM 互作指南。
System.Runtime.InteropServices.COMException:未注册的类(0x80040154(REGDB_E_CLASSNOTREG))
- 如果在从 C++/WinRT 组件使用 C#/WinRT 投影时看到此异常,请确保该组件已通过项目属性或文件将 Windows 桌面兼容属性设置为
.vcxproj。
- 如果在从 C++/WinRT 组件使用 C#/WinRT 投影时看到此异常,请确保该组件已通过项目属性或文件将 Windows 桌面兼容属性设置为
.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 问题页向我们提交问题。