共用方式為


如何將C++/CLI 專案移植到 .NET

從 Visual Studio 2019 開始, C++/CLI 專案 可以以 .NET 為目標。 這項支援可讓您將具有 C++/CLI Interop 層的 Windows 傳統型應用程式從 .NET Framework 移植到 .NET。 本文說明如何將C++/CLI 專案從 .NET Framework 移植到 .NET。

C++/CLI .NET Core 限制

與 .NET Framework 相比,C++/CLI 專案和 .NET 有一些重要的限制:

  • 不支援將C++/CLI 項目編譯為可執行檔。 您必須將其編譯為 DLL。
  • .NET 的C++/CLI 支援僅限 Windows。
  • C++/CLI 項目無法以 .NET Standard 為目標。
  • C++/CLI 項目不支援較新的 SDK 樣式專案檔案格式。 相反地,C++/CLI 專案使用其他 Visual Studio C++專案所使用的相同 .vcxproj 檔格式。
  • C++/CLI 項目無法以多個 .NET 平台為目標。 如果您需要為 .NET 和 .NET Framework 建置C++/CLI 專案,請使用個別的項目檔。
  • .NET 不支援 -clr:pure-clr:safe 編譯,只有較新的 -clr:netcore 選項(相當於 -clr .NET Framework)。

移植C++/CLI 專案

若要將C++/CLI 專案移植到 .NET,請對 .vcxproj 檔案進行下列變更。 這些移轉步驟與其他項目類型所需的步驟不同,因為C++/CLI 專案不會使用 SDK 樣式的項目檔。

  1. 將屬性取代 <CLRSupport>true</CLRSupport><CLRSupport>NetCore</CLRSupport>。 此屬性通常位於組態特定的屬性群組中,因此您可能需要在多個位置取代它。
  2. 將屬性取代 <TargetFrameworkVersion><TargetFramework>net8.0</TargetFramework>。 請務必變更標籤和值。
  3. 移除對SystemSystem.DataSystem.Windows.FormsSystem.Xml等項目的任何 .NET Framework 參考,像<Reference Include="System" />。 使用 <CLRSupport>NetCore</CLRSupport>時,會自動參考 .NET SDK 元件。
  4. 視需要更新 .cpp 檔案中的 API 使用量,以移除 .NET 無法使用的 API。 因為 C++/CLI 專案往往是相當精簡的互操作層,因此通常不需要太多變更。 您可以使用 .NET 可移植性分析器 來識別C++/CLI 二進位檔所使用的不支援的 .NET API。
  5. 如果您的專案是可執行檔,請執行下列步驟:
    1. 將專案類型變更為函式庫。
    2. 建立新的 .NET 可執行文件專案。
    3. 在 .NET 可執行文件專案中,新增對 C++/CLI .NET 庫的參考。

WPF 和 Windows Forms 使用方式

.NET C++/CLI 專案可以使用 Windows Forms 和 WPF API。 若要使用這些 Windows 桌面 API,您必須將明確的架構參考新增至 UI 連結庫。 使用 Windows 桌面 API 的 SDK 樣式專案會自動使用 Microsoft.NET.Sdk.WindowsDesktop SDK 參考必要的框架庫。 由於C++/CLI 專案不會使用 SDK 樣式的專案格式,因此它們必須在以 .NET Core 為目標時新增明確的架構參考。

若要使用 Windows Forms API,請將此參考新增至 .vcxproj 檔案:

<!-- Reference all of Windows Forms -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />

若要使用 WPF API,請將此參考新增至 .vcxproj 檔案:

<!-- Reference all of WPF -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />

若要同時使用 Windows Forms 和 WPF API,請將此參考新增至 .vcxproj 檔案:

<!-- Reference the entirety of the Windows desktop framework:
     Windows Forms, WPF, and the types that provide integration between them -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App" />

目前無法使用 Visual Studio 的參考管理員來新增這些參考。 反而,請手動編輯項目檔來更新。 在 Visual Studio 中,您必須先卸載專案。 您也可以使用另一個編輯器,例如 Visual Studio Code。

不使用 MSBuild 建置

您也可以不使用 MSBuild 來建置C++/CLI 專案。 請遵循下列步驟,直接使用 cl.exelink.exe 建置 C++/CLI 的 .NET Core 專案:

  1. 編譯時,傳遞 -clr:netcorecl.exe

  2. 參考必要的 .NET 參考元件。

  3. 連結時,請提供 .NET 應用程式主機目錄做為 LibPath,以便找到 ijwhost.lib

  4. ijwhost.dll 從 .NET 應用程式主機目錄複製到項目的輸出目錄。

  5. 請確定用於執行受控程式碼的應用程式的第一個元件有 runtimeconfig.json 文件。 針對最新版的Visual Studio,會自動建立並複製 runtime.config 檔案。

    對於舊版 Visual Studio,如果應用程式有原生進入點,您必須手動建立下列runtimeconfig.json檔案,讓第一個 C++ /CLI 連結庫使用 .NET 運行時間。 如果從受控入口點呼叫C++/CLI 連結庫,則該連結庫不需要 runtimeconfig.json 檔案,因為入口點的程序集有在啟動運行時使用的檔案。

    {
       "runtimeOptions": {
          "tfm": "net8.0",
          "framework": {
          "name": "Microsoft.NETCore.App",
          "version": "8.0.0"
          }
       }
    }
    

備註

以 .NET 7 或更新版本為目標的C++/CLI 元件一律會載入預設 AssemblyLoadContext。 不過,在 .NET 6 和更早的版本中,C++/CLI 組件可能會被多次載入,每次都載入到新的 AssemblyLoadContext。 如果第一次執行 C++/CLI 元件中的受控代碼:

  • 原生呼叫程式將組件載入至獨立的AssemblyLoadContext
  • 來自受管理的呼叫端時,元件會載入到與呼叫端相同的 AssemblyLoadContext,通常是預設的。

若要一律將 C++/CLI 元件載入到預設的 AssemblyLoadContext,您可以從您的進入點元件中新增一個「初始化」的樣式呼叫來至 C++/CLI 元件。 如需詳細資訊,請參閱此 dotnet/runtime 問題