通过


C#/WinRT

C#/WinRT 是 NuGet 打包的工具包,它为 C# 语言提供Windows 运行时(WinRT)投影支持。 投影程序集是一个互作程序集,它使 WinRT API 能够以自然且熟悉的方式对目标语言进行编程。 C#/WinRT 投影隐藏了 C# 和 WinRT 接口之间的互操作的详细信息,并提供多种 WinRT 类型与 .NET 对应项的映射,例如字符串、URI、常见值类型和泛型集合。

C#/WinRT 当前通过 .NET 中使用 Target Framework 名字对象(TPM)来支持使用 WinRT API。 使用特定Windows SDK 版本设置 TFM 会添加对 C#/WinRT 生成的Windows SDK 投影和运行时程序集的引用。

使用 C#/WinRT NuGet 包可为.NET使用者创建reference自己的 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 运行时 类型到 .NET 的映射

C#/WinRT 还支持 Windows 应用 SDK 中的组件,包括 WinUI 3。 Windows 应用 SDK将本机Microsoft UI 控件和其他本机组件从操作系统中提升出来。 这使应用开发人员能够在 Windows 10 版本 1809 及更高版本上使用最新的控件和组件。

最后,C#/WinRT 是一个常规工具包,旨在支持在 C# 编译器或.NET运行时中不提供对 WinRT 的内置支持的其他方案。

新动态

可以在 release notes GitHub 页上找到最新的 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 类型:

  1. Contoso.Controls.Widget.dll
  2. Contoso.Controls.dll
  3. Contoso.dll

C#/WinRT 使用 LoadLibrary 备用搜索顺序 查找实现 DLL。 依赖于此回退行为的应用应将实现 DLL 与应用模块一起打包。

常见错误和故障排除

  • 错误:“未提供或检测到 Windows 元数据。”

    可以使用 <CsWinRTWindowsMetadata> 项目属性指定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>
    

    有关指定 属性的详细信息,请参阅 <TargetFramework> 上的文档。

  • 当强制转换为具有特性的接口时,出现异常。

    将对象强制转换为带有ComImport属性的接口时,需要使用.As<>运算符,而非显式使用强制转换表达式。 例如:

    someObject.As<SomeComImportInterface>
    

    有关详细信息,请参阅 COM 互作指南

  • System.Runtime.InteropServices.COMException:未注册的类(0x80040154(REGDB_E_CLASSNOTREG))

    • 如果在从 C++/WinRT 组件使用 C#/WinRT 投影时看到此异常,请确保组件已将 Windows Desktop Compatible 属性设置为 True通过项目属性或通过 .vcxproj 文件。

.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 问题页提交问题

其他资源