通过


C#/WinRT

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 类型:

  1. Contoso.Controls.Widget.dll
  2. Contoso.Controls.dll
  3. 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>
    

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

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

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

    someObject.As<SomeComImportInterface>
    

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

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

    • 如果在从 C++/WinRT 组件使用 C#/WinRT 投影时看到此异常,请确保该组件已通过项目属性或文件将 Windows 桌面兼容属性设置为 .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 问题页向我们提交问题。

其他资源