Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Windows-Desktopanwendungen, die auf .NET Framework abzielen, werden in einer bestimmten Programmiersprache geschrieben und in Zwischensprache (IL) kompiliert. Zur Laufzeit ist ein Just-in-Time-Compiler (JIT) dafür verantwortlich, die IL direkt vor der ersten Ausführung einer Methode in systemeigenen Code für den lokalen Computer zu kompilieren. Im Gegensatz dazu konvertiert die .NET Native-Toolkette den Quellcode während der Kompilierung in nativen Code. In diesem Artikel wird .NET Native mit anderen Kompilierungstechnologien verglichen, die für .NET Framework-Apps verfügbar sind, und bietet auch eine praktische Übersicht darüber, wie .NET Native nativen Code erzeugt, der Ihnen helfen kann, zu verstehen, warum Ausnahmen, die im mit .NET Native kompilierten Code auftreten, nicht in JIT-kompilierten Code auftreten.
Generieren von nativen Binärdateien
Eine Anwendung, die auf .NET Framework ausgerichtet ist und nicht mithilfe der .NET Native-Toolkette kompiliert wird, besteht aus der Anwendungsassembly, die Folgendes enthält:
Metadaten, die die Assembly, deren Abhängigkeiten, die darin enthaltenen Typen und deren Mitglieder beschreiben. Die Metadaten werden für Reflexion und spätgebundenen Zugriff und in einigen Fällen auch von Compiler- und Build-Tools verwendet.
Implementierungscode. Dies besteht aus Opcodes der Intermediate Language (IL). Zur Laufzeit übersetzt der JUST-in-Time(JIT)-Compiler sie in systemeigenen Code für die Zielplattform.
Zusätzlich zur Hauptassembly einer Anwendung muss Folgendes bei einer App vorhanden sein:
Alle zusätzlichen Klassenbibliotheken oder Assemblys von Drittanbietern, die von Ihrer App benötigt werden. Diese Assemblys enthalten ähnlich Metadaten, die die Assembly, deren Typen und ihre Member beschreiben, sowie die IL, die alle Typmember implementiert.
Die .NET Framework-Klassenbibliothek. Dies ist eine Sammlung von Assemblys, die mit der .NET Framework-Installation auf dem lokalen System installiert sind. Die Assemblys, die in der .NET Framework-Klassenbibliothek enthalten sind, enthalten einen vollständigen Satz von Metadaten und Implementierungscode.
Die Common Language Runtime. Dies ist eine Sammlung dynamischer Linkbibliotheken, die Dienste wie Assembly-Laden, Speicherverwaltung und Speicherbereinigung, Ausnahmebehandlung, JIT-Kompilierung, Remoting und Interoperabilität ausführen. Wie die Klassenbibliothek wird die Laufzeit im lokalen System als Teil der .NET Framework-Installation installiert.
Beachten Sie, dass die gesamte Common Language Runtime sowie Metadaten und IL für alle Typen in anwendungsspezifischen Assemblys, Assemblys von Drittanbietern und Systemassemblys vorhanden sein müssen, damit die App erfolgreich ausgeführt werden kann.
Just-in-Time-Kompilierung
Die Eingabe für die .NET Native-Toolkette ist die UWP-App, die vom C#- oder Visual Basic-Compiler erstellt wurde. Anders ausgedrückt: Die .NET Native-Toolkette beginnt mit der Ausführung, wenn der Sprachcompiler die Kompilierung einer UWP-App abgeschlossen hat.
Tipp
Da die Eingabe in .NET Native aus IL und Metadaten besteht, die in verwaltete Assemblys geschrieben sind, können Sie dennoch benutzerdefinierte Codegenerierungen oder andere spezielle Operationen durchführen, indem Sie Vor-Build- oder Post-Build-Ereignisse nutzen oder die MSBuild-Projektdatei ändern.
Kategorien von Tools, die IL ändern und dadurch verhindern, dass die .NET-Toolkette den IL-Code einer App analysiert, werden nicht unterstützt. Verschleierer sind die bekanntesten Werkzeuge dieser Art.
Im Verlauf der Konvertierung einer App von IL in systemeigenen Code führt die .NET Native-Toolkette Vorgänge wie die folgenden aus:
Bei bestimmten Codepfaden ersetzt sie Code, der auf Reflexion und Metadaten basiert, durch statischen nativen Code. Wenn z. B. ein Werttyp die ValueType.Equals-Methode nicht überschreibt, verwendet der Standardtest für Gleichheit Reflection, um FieldInfo-Objekte abzurufen, die die Felder des Werttyps darstellen, und vergleicht anschließend die Feldwerte zweier Instanzen. Beim Kompilieren in nativen Code ersetzt die .NET Native-Toolkette den Reflexionscode und die Metadaten durch einen statischen Vergleich der Feldwerte.
Wenn möglich, wird versucht, alle Metadaten zu beseitigen.
Sie enthält in den endgültigen App-Assemblys nur den Implementierungscode, der tatsächlich von der App aufgerufen wird. Dies wirkt sich insbesondere auf Code in Drittanbieterbibliotheken und in der .NET Framework-Klassenbibliothek aus. Daher hängt eine Anwendung nicht mehr von Drittanbieterbibliotheken oder von der vollständigen .NET Framework-Klassenbibliothek ab; Stattdessen ist Code in Drittanbieter- und .NET Framework-Klassenbibliotheken jetzt lokal für die App.
Er ersetzt die vollständige CLR durch eine umgestaltete Laufzeit, die in erster Linie den Garbage Collector enthält. Die umgestaltete Laufzeit befindet sich in einer Bibliothek mit dem Namen mrt100_app.dll, die lokal für die App ist und nur ein paar hundert Kilobyte groß ist. Dies ist möglich, da statisches Linking die Notwendigkeit für viele der von der Common Language Runtime ausgeführten Dienste eliminiert.
Hinweis
.NET Native verwendet denselben Garbage Collector wie die Standard-Common Language Runtime. Im .NET Native-Garbage-Collector ist die Hintergrund-Garbage-Collection standardmäßig aktiviert. Weitere Informationen zur Speicherbereinigung finden Sie unter Grundlagen der Speicherbereinigung.
Von Bedeutung
.NET Native kompiliert eine gesamte Anwendung zu einer systemeigenen Anwendung. Sie können keine einzelne Assembly, die eine Klassenbibliothek enthält, in nativen Code kompilieren, um sie unabhängig vom verwalteten Code aufrufen zu können.
Die resultierende App, die von der .NET Native-Toolkette erstellt wird, wird in ein Verzeichnis mit dem Namen "ilc.out" im Debug- oder Releaseverzeichnis Ihres Projektverzeichnisses geschrieben. Sie besteht aus den folgenden Dateien:
<appName>.exe, ein Stub-Executable, das einfach die Kontrolle an einen speziellen
Main-Export in <appName>.dllüberträgt.<"appName> ".dll, eine Windows-Bibliothek mit dynamischem Link, die ihren gesamten Anwendungscode enthält, sowie Code aus der .NET Framework-Klassenbibliothek und allen Drittanbieterbibliotheken, von denen Sie abhängig sind. Sie enthält auch Unterstützungscode, z. B. den Code, der für die Interoperabilität mit Windows erforderlich ist, und zum Serialisieren von Objekten in Ihrer App.
mrt100_app.dll, eine umgestaltete Laufzeitumgebung, die Laufzeitdienste wie Speicherbereinigung bereitstellt.
Alle Abhängigkeiten werden vom APPX-Manifest der App erfasst. Neben der Anwendung exe, dll und mrt100_app.dll, die direkt im appx-Paket gebündelt sind, umfasst dies zwei weitere Dateien:
msvcr140_app.dll, die C-Laufzeitbibliothek (CRT), die von mrt100_app.dllverwendet wird. Es ist in einer Framework-Referenz im Paket enthalten.
mrt100.dll. Diese Bibliothek enthält Funktionen, die die Leistung von mrt100_app.dllverbessern können, obwohl deren Fehlen nicht verhindert, dass mrt100_app.dll funktioniert. Sie wird aus dem System32-Verzeichnis auf dem lokalen Computer geladen, falls vorhanden.
Da der .NET Native Toolchain Implementierungscode nur dann mit Ihrer App verknüpft, wenn sie weiß, dass ihre App diesen Code tatsächlich aufruft, sind die Metadaten oder der in den folgenden Szenarien erforderliche Implementierungscode möglicherweise nicht in Ihre App eingeschlossen:
Reflexion.
Dynamischer oder verspäteter Aufruf.
Serialisierung und Deserialisierung.
COM-Interoperabilität.
Wenn der erforderliche Metadaten- oder Implementierungscode zur Laufzeit nicht vorhanden ist, löst die .NET Native-Laufzeit eine Ausnahme aus. Sie können diese Ausnahmen verhindern und sicherstellen, dass die .NET Native-Toolkette den erforderlichen Metadaten- und Implementierungscode enthält, indem Sie eine Laufzeitdirektivendatei verwenden, eine XML-Datei, die die Programmelemente bestimmt, deren Metadaten oder Implementierungscode zur Laufzeit verfügbar sein müssen, und ihnen eine Laufzeitrichtlinie zuweist. Die folgende Standardlaufzeitrichtliniendatei wird einem UWP-Projekt hinzugefügt, welches von der .NET Native-Werkzeugkette kompiliert wird.
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="*Application*" Dynamic="Required All" />
</Application>
</Directives>
Dadurch werden alle Typen sowie all ihre Mitglieder in allen Assemblys Ihres App-Pakets für Reflektion und dynamische Aufrufe ermöglicht. Jedoch wird keine Reflektion oder dynamische Typaktivierung in .NET Framework-Klassenbibliotheken-Assemblies ermöglicht. In vielen Fällen ist dies angemessen.