共用方式為


C#/WinRT

C#/WinRT 是一個以 NuGet 封裝的工具包,提供 Windows 執行時(WinRT)投影支援,適用於 C# 語言。 投影組合是一種互操作組合語言,使 WinRT API 能夠以自然且熟悉的方式編寫,以符合目標語言的需求。 C#/WinRT 投影隱藏了 C# 與 WinRT 介面間的互通細節,並提供多種 WinRT 類型與適當的 .NET 等價物的映射,如字串、URI、常見值類型及通用集合。

C#/WinRT 目前在 .NET 中透過 目標框架名稱 (TFM) 支援使用 WinRT API。 將 TFM 設定為特定 Windows SDK 版本,會新增對 Windows SDK 投影與執行時組件的參考,這些集合由 C#/WinRT 產生。

C#/WinRT NuGet 套件讓您能為 .NET 使用者建立參考您自己的 WinRT 互操作組件。 最新的 C#/WinRT 版本也包含 C# 中 WinRT 類型開發的預覽。

欲了解更多資訊,請參閱 C#/WinRT GitHub 倉庫

C#/WinRT 的動機

.NET (前稱 .NET Core)是一款開源、跨平台的執行環境,可用於建置裝置、雲端及物聯網應用程式。

先前版本的 .NET Framework 與 .NET Core 內建 WinRT 知識——一種 Windows 專用技術。 為了支援 .NET 6+ 的可攜性與效率目標,我們將 WinRT 投影支援從 .NET 編譯器和執行時移除,移至 C#/WinRT 工具包中(參見 .NET 已移除 WinRT 內建支援)。 C#/WinRT 的目標是與早期版本的 C# 編譯器和 .NET 執行時內建的 WinRT 支援提供同等的支援。 詳情請參閱 Windows 執行時類型的 .NET 映射

C#/WinRT 也支援 Windows 應用程式 SDK 中的元件,包括 WinUI。 Windows App SDK 將原生 Microsoft UI 控制項及其他原生元件從作業系統中移除。 這讓應用程式開發者能在 Windows 10、版本 1809 及之後版本中使用最新的控制項與元件。

最後,C#/WinRT 是一個通用工具包,旨在支援其他 C# 編譯器或 .NET 執行環境中沒有內建 WinRT 支援的情況。

有什麼新鮮事

最新的 C#/WinRT 版本可在我們 Github 倉庫的 版本說明 頁面找到。

Usage

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# 投影,作為 NuGet 發佈給 .NET 應用程式」。

參考互通組件

通常,C#/WinRT 的互操作組件會被應用程式專案引用。 但它們也可能被中間互操作組件所引用。 例如,WinUI 的互操作組件會參考 Windows SDK 的互操作組件。

如果你發佈第三方 WinRT 元件而沒有官方的互操作組件,應用程式專案可能會依照 產生互操作組件 的程序,產生自己的私人投影來源。 我們不建議採用此方法,因為它可能在流程中產生相同類型的相互衝突的預測。 NuGet 封裝採用 語意版本管理(Semantic Versioning )機制,旨在防止這種情況。 偏好官方第三方互操作組裝。

對 WinRT 類型的內嵌支援(預覽版)

從 C#/WinRT 1.4.1 版本開始,支援將 Windows SDK 投影與執行時來源(適用於 .NET 與 .NET Standard 2.0)嵌入函式庫或應用程式的輸出中。 這在 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 相容性設定為 .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'(你是否缺少使用指令或組合語言參考?)

    為了解決這個錯誤,請編輯你的 <TargetFramework> 屬性以鎖定特定的 Windows 版本,例如:

    <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
    

    有關指定該屬性的更多細節,請參閱「<TargetFramework>的文件。

  • System.InvalidCastException 當轉型至具有ComImport屬性的介面時

    當將物件轉型到帶有 ComImport 屬性的介面時,你需要使用 .As<> 運算子,而不是使用顯式 轉型運算式。 例如:

    someObject.As<SomeComImportInterface>
    

    更多細節請參閱 COM 互操作指南

  • System.Runtime.InteropServices.COMException:類別未註冊(0x80040154(REGDB_E_CLASSNOTREG))

    • 如果你在使用 C++/WinRT 元件的 C#/WinRT 投影時看到此異常,請確保該元件已將 Windows 桌面相容屬性設為 True,無論是透過專案屬性還是檔案。.vcxproj

.NET SDK 版本控制錯誤

你可能會遇到以下錯誤或警告,若專案使用比任何相依套件更早的 .NET SDK 版本。

錯誤或警告訊息 原因
警告MSB3277:發現不同版本的 WinRT.Runtime 或 Microsoft.Windows.SDK.NET 之間存在無法解決的衝突。 此建置警告發生在參考一個在 API 表面暴露 Windows SDK 型別的函式庫時。
錯誤 CS1705:組件 'AssemblyName1' 使用了 'TypeName',其版本高於參考的組件 'AssemblyName2' 此建置編譯器錯誤發生在參考並使用函式庫中暴露的 Windows SDK 型別時。
System.IO.FileLoadException 此執行時錯誤可能發生在呼叫未公開 Windows SDK 型別的函式庫中的特定 API。

要修正這些錯誤,請將你的 .NET SDK 更新到最新版本。 這樣做可以確保你的應用程式所使用的執行時和 Windows SDK 組合語言版本與所有相依性相容。 這些錯誤可能發生在 .NET SDK 的早期服務或功能更新時,因為執行時修正可能需要更新組合語言版本。

已知問題

已知問題與破壞性變更會在 C#/WinRT GitHub 倉庫中標示。

如果您在使用 C#/WinRT NuGet 套件、cswinrt.exe 編譯器或產生的投影原始碼時遇到任何功能問題,請透過 C#/WinRT 問題頁面向我們提交問題。

其他資源