Portieren eines C++/CLI-Projekts zu .NET
Ab Visual Studio 2019 können C++/CLI-Projekte auf .NET abzielen. Diese Unterstützung ermöglicht das Portieren von Windows-Desktopanwendungen mit C++/CLI-Interopebenen von .NET Framework zu .NET. In diesem Artikel wird beschrieben, wie Sie C++/CLI-Projekte von .NET Framework zu .NET portieren können.
C++/CLI-Einschränkungen für .NET Core
Es gibt einige wichtige Einschränkungen bei C++/CLI-Projekten und .NET im Vergleich zu .NET Framework:
- Das Kompilieren eines C++/CLI-Projekts zu einer ausführbaren Datei wird nicht unterstützt. Sie müssen zu einer DLL kompilieren.
- C++/CLI wird nur unter Windows für .NET unterstützt.
- C++/CLI-Projekte können nicht auf .NET Standard abzielen.
- C++/CLI-Projekte unterstützen nicht das neuere SDK-Format für Projektdateien. Stattdessen verwenden C++/CLI-Projekte das gleiche .vcxproj-Dateiformat, das andere Visual Studio C++-Projekte verwenden.
- C++/CLI-Projekte können nicht mit mehreren .NET-Plattformen kompatibel sein. Wenn Sie ein C++/CLI-Projekt erstellen möchten, dass sowohl unter .NET als auch unter .NET Framework verwendet werden kann, müssen Sie separate Projektdateien verwenden.
- .Net unterstützt keine
-clr:pure
- oder-clr:safe
-Kompilierung, sondern nur die neuere-clr:netcore
-Option (die-clr
für .NET Framework entspricht).
Portieren eines C++/CLI-Projekts
Wenn Sie ein C++/CLI-Projekt zu .NET portieren möchten, nehmen Sie die folgenden Änderungen an der .vcxproj-Datei vor. Der Ablauf dieser Migration unterscheidet sich vom Ablauf bei anderen Projekttypen, da bei C++/CLI-Projekten keine SDK-Projektdateien verwendet werden.
- Ersetzen Sie
<CLRSupport>true</CLRSupport>
-Eigenschaften durch<CLRSupport>NetCore</CLRSupport>
. Diese Eigenschaft ist häufig in konfigurationsspezifischen Eigenschaftengruppen enthalten. Deshalb müssen Sie sie möglicherweise an mehreren Stellen ersetzen. - Ersetzen Sie
<TargetFrameworkVersion>
-Eigenschaften durch<TargetFramework>net8.0</TargetFramework>
. Achten Sie darauf, das Tag und den Wert zu ändern. - Entfernen Sie alle .NET Framework-Verweise auf
System
,System.Data
,System.Windows.Forms
undSystem.Xml
, z. B.<Reference Include="System" />
. Wenn<CLRSupport>NetCore</CLRSupport>
verwendet wird, wird automatisch auf .NET SDK-Assemblys verwiesen. - Aktualisieren Sie ggf. die API-Nutzung in .cpp-Dateien, um APIs zu entfernen, die für .NET nicht verfügbar sind. Da es sich bei C++/CLI-Projekten in der Regel um relativ dünne Interopebenen handelt, müssen oft nur wenige Änderungen vorgenommen werden. Sie können die .NET-Portabilitätsanalyse verwenden, um nicht unterstützte .NET-APIs zu identifizieren, die von C++/CLI-Binärdateien verwendet werden.
- Wenn Ihr Projekt eine ausführbare Datei war, führen Sie die folgenden Schritte aus:
- Ändern Sie den Projekttyp in eine Bibliothek.
- Erstellen Sie ein neues ausführbares .NET-Projekt.
- Fügen Sie im ausführbaren .NET-Projekt einen Verweis auf die C++/CLI .NET-Bibliothek hinzu.
Nutzung von WPF und Windows Forms
C++/CLI-Projekte für .NET können Windows Forms- und WPF-APIs verwenden. Damit Sie diese Windows-Desktop-APIs verwenden können, müssen Sie explizite Frameworkverweise auf die Benutzeroberflächenbibliotheken hinzufügen. SDK-Projekte, die Windows-Desktop-APIs verwenden, verweisen automatisch unter Verwendung des Microsoft.NET.Sdk.WindowsDesktop
SDK auf die erforderlichen Frameworkbibliotheken. Da C++/CLI-Projekte nicht das SDK-Projektformat verwenden, müssen explizite Frameworkverweise hinzugefügt werden, wenn ein Projekt auf .NET Core ausgerichtet ist.
Damit Windows Forms-APIs verwendet werden können, fügen Sie der .vcxproj-Datei folgenden Verweis hinzu:
<!-- Reference all of Windows Forms -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WindowsForms" />
Damit WPF-APIs verwenden können, fügen Sie der .vcxproj-Datei folgenden Verweis hinzu:
<!-- Reference all of WPF -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App.WPF" />
Damit sowohl Windows Forms- als auch WPF-APIs verwendet werden können, fügen Sie der .vcxproj-Datei folgenden Verweis hinzu:
<!-- Reference the entirety of the Windows desktop framework:
Windows Forms, WPF, and the types that provide integration between them -->
<FrameworkReference Include="Microsoft.WindowsDesktop.App" />
Derzeit ist es nicht möglich, diese Verweise mithilfe des Verweis-Managers von Visual Studio hinzuzufügen. Aktualisieren Sie die Projektdatei stattdessen manuell. In Visual Studio müssen Sie das Projekt zuerst entladen. Sie können auch einen anderen Editor wie z. B. Visual Studio Code verwenden.
Build ohne MSBuild
Es ist auch möglich, C++/CLI-Projekte ohne MSBuild zu erstellen. Führen Sie die folgenden Schritte aus, um direkt mithilfe der Dateien cl.exe und link.exe ein C++/CLI-Projekt für .NET Core zu erstellen:
Übergeben Sie bei der Kompilierung
-clr:netcore
an cl.exe.Verweisen Sie auf erforderliche Referenzassemblys für .NET.
Geben Sie bei der Verknüpfung das Verzeichnis für den .NET-App-Host als
LibPath
an, damit die Datei ijwhost.lib gefunden werden kann.Kopieren Sie ijwhost.dll aus dem Verzeichnis des .NET-App-Hosts in das Ausgabeverzeichnis des Projekts.
Stellen Sie sicher, dass für die erste Komponente der Anwendung, die verwalteten Code ausführt, eine runtimeconfig.json Datei vorhanden ist. Für die neuesten Versionen von Visual Studio wird eine Runtime.config-Datei erstellt und automatisch kopiert.
Bei älteren Versionen von Visual Studio müssen Sie, wenn die Anwendung über einen systemeigenen Einstiegspunkt verfügt, die folgende runtimeconfig.json Datei für die erste C++/CLI-Bibliothek erstellen, um die .NET-Laufzeit zu verwenden. Wenn eine C++/CLI-Bibliothek von einem verwalteten Einstiegspunkt aufgerufen wird, benötigt die Bibliothek keine runtimeconfig.json Datei, da die Einstiegspunktassembly eine hat, die beim Starten der Laufzeit verwendet wird.
{ "runtimeOptions": { "tfm": "net8.0", "framework": { "name": "Microsoft.NETCore.App", "version": "8.0.0" } } }
Hinweis
C++/CLI-Assemblys für .NET 7 oder eine höhere Version werden immer in den standardmäßigen AssemblyLoadContext geladen. In .NET 6 und früheren Versionen können C++/CLI-Assemblys jedoch mehrmals geladen werden, jedes Mal in eine neue AssemblyLoadContext
. Wenn der verwaltete Code zum ersten Mal in einer C++/CLI-Assembly ausgeführt wird:
- Stammt von einem systemeigenen Aufrufer, wird die Assembly in eine separate
AssemblyLoadContext
geladen. - Stammt von einem verwalteten Aufrufer, wird die Assembly in die gleiche
AssemblyLoadContext
wie der Aufrufer geladen, in der Regel die Standardeinstellung.
Damit Ihre C++/CLI-Assembly immer in den standardmäßigen AssemblyLoadContext
geladen wird, können Sie der Assembly einen initialize-Aufruf von der Einstiegspunktassembly hinzufügen. Weitere Informationen finden Sie in diesem dotnet/runtime-Issue.