Diese Seite kann automatisch übersetzten Text enthalten.

So entwickeln Sie Native AOT-Anwendungen in .NET

.NET 8 bietet umfassende Unterstützung für die Ahead-of-Time-Kompilierung, auch bekannt als Native AOT. Solche Anwendungen starten normalerweise schneller und verbrauchen weniger Speicher als verwaltete Lösungen.

Die .NET AOT-Veröffentlichung erzeugt abgespeckte, in sich geschlossene Anwendungen. Solche Anwendungen:

  1. Können auf einem Computer ausgeführt werden, auf dem die .NET-Runtime nicht installiert ist.
  2. Zielen auf eine bestimmte Runtime-Umgebung ab, z. B. Windows x64.
  3. Enthalten keinen ungenutzten Code.

.NET AOT-Anwendungen bereitstellen

Wir entwickeln die Docotic.Pdf-Bibliothek zur PDF-Verarbeitung. Die AOT-Kompatibilität ist eine der beliebtesten Funktionsanfragen im Jahr 2024. Dieser Artikel beschreibt unseren Weg zur Erreichung der AOT-Kompatibilität. Sie erfahren, wie Sie AOT-Probleme in .NET-Projekten finden und beheben.

Grundlagen der .NET AOT-Veröffentlichung

Um eine Native AOT-Anwendung zu veröffentlichen, fügen Sie Ihrer Projektdatei die folgende Eigenschaft hinzu:

<PropertyGroup>
    <PublishAot>true</PublishAot>
</PropertyGroup>

Möglicherweise müssen Sie auch einige Voraussetzungen installieren. Anschließend können Sie Ihre App aus Visual Studio veröffentlichen. Oder Sie können das Projekt über die Befehlszeile mit dem Befehl dotnet publish veröffentlichen:

dotnet publish -r linux-x64 -c Release

AOT-Kompatibilität für .NET-Bibliotheken

Die Native AOT-Veröffentlichung ist in .NET 7 und .NET 8 verfügbar. In .NET 7 können Sie nur Konsolenanwendungen veröffentlichen. In .NET 8 können Sie zusätzlich ASP.NET Core-Anwendungen veröffentlichen.

Aber die Docotic.Pdf-Kernbibliothek zielt auf .NET Standard 2.0 ab. Können wir sie AOT-freundlich machen? Natürlich.

Sie können AOT-Kompatibilitätsprobleme in .NET-Bibliotheken, die auf .NET Standard, .NET 5 oder .NET 6 abzielen, weiterhin finden und beheben. Native AOT-Anwendungen können dann auf die Bibliothek zurückgreifen.

AOT-Probleme finden

Unsere erste Supportanfrage zur AOT-Kompatibilität lautet wie folgt:

Wir erwägen, Docotic.Pdf zu verwenden, das in WebAssembly kompiliert wurde. Es erzeugt Trimmwarnungen, wenn wir es in AOT kompilieren:
Warnung IL2104: Assembly 'BitMiracle.Docotic.Pdf' hat Trimmwarnungen erzeugt. Weitere Informationen finden Sie unter https://aka.ms/dotnet-illink/libraries

Nicht sehr informativ. Lassen Sie uns das Problem reproduzieren und mehr Details zu diesen Trimmwarnungen erhalten.

Veröffentlichungswarnungen erhalten

Das Veröffentlichen einer Testanwendung ist die flexibelste Möglichkeit, .NET AOT-Probleme zu finden. Sie müssen:

  1. Ein .NET 8-Konsolenprojekt mit PublishAot = true erstellen
  2. Eine Referenz zu Ihrem Projekt hinzufügen und einige seiner Typen verwenden

Hier ist die csproj-Konfiguration, die wir für Docotic.Pdf verwenden:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PublishAot>true</PublishAot>
        <TrimmerSingleWarn>false</TrimmerSingleWarn>
        <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
        <WarningsAsErrors />
    </PropertyGroup>

    <ItemGroup>
        <ProjectReference Include="..\Docotic\Docotic.csproj" />
    </ItemGroup>
</Project>

Mit TrimmerSingleWarn = false können Sie detaillierte Informationen zu Warnungen erhalten. Andernfalls erhalten Sie nur die Meldung „Assembly 'X' hat Trimmwarnungen erzeugt“.

Und hier ist der C#-Code in Program.cs:

using BitMiracle.Docotic.Pdf;

using var pdf = new PdfDocument();

Fügen Sie Code hinzu, um das Laden der zu prüfenden Assembly zu erzwingen. Es ist nicht erforderlich, alle Funktionen Ihres Projekts abzudecken, um Veröffentlichungswarnungen zu erhalten. Die Verwendung eines einzelnen Typs reicht aus. Sie müssen jedoch mehr Code schreiben, um Laufzeitfehler abzufangen.

Der Befehl dotnet publish -r win-x64 -c Release für dieses Projekt hat Trim- und AOT-Warnungen zurückgegeben. Hier ist die Kurzfassung der Liste:

AOT-Analysewarnung IL3050: Org.BouncyCastle.Utilities.Enums.GetEnumValues(Type): Die Verwendung des Mitglieds 'System.Enum.GetValues(Type)', das 'RequiresDynamicCodeAttribute' hat, kann die Funktionalität beim AOT-Kompilieren beeinträchtigen.

Trim-Analysewarnung IL2026: LogProviders.Log4NetLogProvider.Log4NetLogger.GetCreateLoggingEvent(ParameterExpression,UnaryExpression,ParameterExpression,UnaryExpression,Type): Die Verwendung des Mitglieds 'System.Linq.Expressions.Expression.Property(Expression,String)', das 'RequiresUnreferencedCodeAttribute' hat, kann beim Kürzen des Anwendungscodes die Funktionalität beeinträchtigen.

Trim-Analysewarnung IL2057: LogProviders.LogProviderBase.FindType(String,String[]): Unbekannter Wert an den Parameter 'typeName' der Methode 'System.Type.GetType(String)' übergeben..

Trim-Analysewarnung IL2070: LogProviders.NLogLogProvider.NLogLogger.GetIsEnabledDelegate(Type,String): 'this'-Argument erfüllt 'DynamicallyAccessedMemberTypes.PublicProperties' im Aufruf von 'System.Type.GetProperty(String)' nicht. Der Parameter „loggerType“ der Methode „LogProviders.NLogLogProvider.NLogLogger.GetIsEnabledDelegate(Type,String)“ hat keine übereinstimmenden Anmerkungen. Der Quellwert muss mindestens dieselben Anforderungen deklarieren wie diejenigen, die am Zielort deklariert sind, dem er zugewiesen ist.

Trim-Analysewarnung IL2075: LogProviders.Log4NetLogProvider.GetOpenNdcMethod(): Das Argument 'this' erfüllt 'DynamicallyAccessedMemberTypes.PublicProperties' im Aufruf von 'System.Type.GetProperty(String)' nicht. Der Rückgabewert der Methode 'LogProviders.LogProviderBase.FindType(String,String)' hat keine übereinstimmenden Anmerkungen. Der Quellwert muss mindestens dieselben Anforderungen deklarieren wie die, die am Zielort deklariert sind, dem er zugewiesen ist.

Wir haben die Grundursache gefunden. Bevor wir die Probleme beheben, prüfen wir alternative Optionen, um AOT-Kompatibilitätsprobleme zu finden.

Verwenden Sie AOT-Kompatibilitätsanalysatoren

Microsoft stellt Roslyn-Analysatoren zur Verfügung, um AOT-Probleme in .NET 7- oder .NET 8-Projekten zu finden. Sie können AOT-Probleme hervorheben, wenn Sie den Code schreiben. Aber die Veröffentlichung einer Testanwendung erkennt noch mehr Probleme.

Um die statische Analyse zu verwenden, fügen Sie der .csproj-Datei die folgende Eigenschaft hinzu:

<PropertyGroup>
    <IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

Sie müssen das .NET 7- oder .NET 8-Framework als Ziel verwenden, um eine solche Analyse in einem .NET Standard 2.0-Projekt zu verwenden. Die Projektkonfiguration kann folgendermaßen aussehen:

<PropertyGroup>
    <TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
    <IsAotCompatible Condition="'$(TargetFramework)'=='net8.0'">true</IsAotCompatible>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <WarningsAsErrors />
</PropertyGroup>

Wir haben die obige Konfiguration auf unser großes Kernprojekt angewendet und 1036 Build-Fehler erhalten.

Viele Build-Fehler

Bezogen sie sich alle auf die AOT-Kompatibilität? Wir hatten das Projekt ohne die Eigenschaft IsAotCompatible neu erstellt. Trotzdem 1036 Fehler.

Alle Fehler bezogen sich auf die Verbesserungen in .NET 8 im Vergleich zu .NET Standard 2.0. In unserem Fall drehten sich die meisten Probleme um die bessere Unterstützung für nullbare Referenztypen. Es gab auch viele CA1500- und CA1512-Fehler bezüglich der neuen Hilfsmethoden ArgumentOutOfRangeException.ThrowIfLessThan und ArgumentNullException.ThrowIfNull.

Wir haben alle Fehler behoben und die Eigenschaft IsAotCompatible aktiviert. Der Projektaufbau wurde ohne AOT-Fehler abgeschlossen. Die statische Analyse hat keine der während des Veröffentlichungsprozesses gefundenen Warnungen erkannt 🙁

Zur Bestätigung haben wir unserer Codebasis den folgenden Testcode hinzugefügt:

Type t = typeof(int);
t = typeof(List<>).MakeGenericType(t);
Console.WriteLine(Activator.CreateInstance(t));

string s = Console.ReadLine() ?? string.Empty;
Type? type = Type.GetType(s);
if (type != null)
{
    foreach (var m in type.GetMethods())
        Console.WriteLine(m.Name);
}

Dieser C#-Code ist zu 100 % inkompatibel mit .NET AOT und Trimming. Und die statische Analyse hat die folgenden Fehler identifiziert:

Fehler IL3050: Die Verwendung des Mitglieds 'System.Type.MakeGenericType(params Type[])', das 'RequiresDynamicCodeAttribute' hat, kann die Funktionalität beim Kompilieren von AOT beeinträchtigen. Der native Code für diese Instanziierung ist möglicherweise zur Laufzeit nicht verfügbar.

Fehler IL2057: Unbekannter Wert an den Parameter 'typeName' der Methode 'System.Type.GetType(String)' übergeben. Die Verfügbarkeit des Zieltyps kann nicht garantiert werden.

Roslyn-Analysatoren funktionieren also und können einige Probleme finden. In unserem Fall haben sie nichts gefunden.

Laufzeitfehler abfangen

Der Artikel So machen Sie Bibliotheken mit Native AOT kompatibel gibt das folgende Prinzip an:

Wenn eine Anwendung beim Veröffentlichen für AOT keine Warnungen aufweist, verhält sie sich nach AOT genauso wie ohne AOT.

In der Praxis kann die Version nach AOT immer noch anders funktionieren. Wir haben alle AOT- und Trimmwarnungen behoben. Alle automatischen Tests bestanden. Die Testanwendung verarbeitete PDF-Dokumente ordnungsgemäß. Und die AOT-Version derselben Anwendung produzierte falsche Dokumente.

Die AOT-Anwendung funktionierte immer noch nicht

Beim Veröffentlichen von AOT wurde versehentlich erforderlicher Code entfernt. Wir haben das Problem Optimierung entfernt erforderlichen Code verursacht. Das .NET-Team hat es schnell bestätigt und behoben. Und wir haben unserem C#-Code einen Workaround hinzugefügt, bis der Fix verfügbar ist.

Die Moral dieser Geschichte ist, dass Veröffentlichungs- und statische Analysewarnungen möglicherweise nicht ausreichen. Verwenden Sie die Hauptfunktionen Ihres Projekts in der Testanwendung. Und führen Sie die Testanwendung nach der Bereitstellung aus.

Die Docotic.Pdf-Testanwendung verwendet PDF-Komprimierung, Textextraktion und andere wichtige Funktionen. Wir verwenden sie folgendermaßen:

AotCompatibility.exe compress "C:\compressed.pdf" "C:\input.pdf" "optional-password"

Das manuelle Testen der veröffentlichten Anwendung ist nicht bequem. Es lohnt sich, den Prozess zu automatisieren.

AOT-Probleme automatisch erkennen

Die Entwicklung von Docotic.Pdf basiert auf automatischen Tests. Es gibt Tests für jedes Feature oder jeden Bug. Die .NET AOT-Kompatibilität ist keine Ausnahme.

Es gibt zwei Möglichkeiten, das Testen von Native AOT-Anwendungen zu automatisieren.

Platzieren Sie Tests außerhalb der AOT-Anwendung

Hier verwenden Sie ein reguläres NUnit/xUnit/MSTest-Projekt. Bevor Sie dieses Projekt erstellen, veröffentlichen Sie die AOT-Testanwendung. Die Tests führen die veröffentlichte App mit der Methode Process.Start aus.

Der Hauptvorteil ist die Trennung der Testinfrastruktur von der AOT-App. Sie können die vollständigen Funktionen von Unit-Test-Frameworks nutzen. Eventuelle AOT-Kompatibilitätsprobleme im Test-Framework spielen keine Rolle. Es ist auch einfacher, vorhandene Testfälle wiederzuverwenden.

Die Beispielkonfiguration des Testprojekts ist auf GitHub verfügbar. Das Projekt Docotic.Tests enthält automatische Tests für verwaltete und AOT-Versionen. AotCompatibility ist eine Testanwendung für die AOT-Veröffentlichung.

Das AotCompatibility.csproj veröffentlicht die Testanwendung bei einem Post-Build-Ereignis in der Release-Konfiguration. Die Bedingung '$(PublishProtocol)'=='' deaktiviert diesen Schritt, wenn Sie den Assistenten „Veröffentlichen“ in Visual Studio verwenden.

<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release' And '$(PublishProtocol)'==''">
    <Exec Command="&quot;$(SolutionDir)Scripts\publish.bat&quot;" />
</Target>

Das Skript publish.bat ist einfach:

@echo off

SET AOT_TEST_DIR=%~dp0\..\AotCompatibility
dotnet publish "%TRIM_TEST_DIR%\AotCompatibility.csproj" --no-build /warnaserror /p:PublishProfile="%AOT_TEST_DIR%\Properties\PublishProfiles\win-x64-installer.pubxml"

Beachten Sie, dass wir hier das Argument --no-build verwenden. Das Projekt wurde bereits vor dem Post-Build-Ereignis erstellt. Wir müssen es nicht erneut erstellen.

Die Tests in NativeAot.cs führen die veröffentlichte AotCompatibility.exe mit unterschiedlichen Argumenten aus. Docotic.Tests- und AotCompatibility-Projekte teilen denselben getesteten Code. Dadurch können wir verwaltete und AOT-Versionen überprüfen, ohne Code zu duplizieren.

Platzieren Sie Tests innerhalb der AOT-Anwendung

Ein alternativer Ansatz besteht darin, Tests innerhalb der AOT-Testanwendung zu schreiben. Im Juli 2024 können Sie nur die frühe Vorschau von MS Test verwenden. Lesen Sie den Artikel Testen Ihrer nativen AOT-Anwendungen für weitere Einzelheiten.

Das Hauptproblem ist, dass jedes AOT-Problem im Testframework Ihre Tests unzuverlässig macht. Und es steht nur ein begrenzter Satz von Testframework-Funktionen zur Verfügung. Deshalb bevorzugen wir es, die Testinfrastruktur außerhalb der AOT-Anwendung zu platzieren.

AOT- und Trimmwarnungen beheben

Vermeiden Sie das Unterdrücken von Veröffentlichungswarnungen. Normalerweise ist das Unterdrücken eine falsche Lösung. Wenn Sie AOT- oder Trim-Warnungen unterdrücken, sagen Sie, dass Ihr Projekt AOT-kompatibel ist. Die Grundursache der Warnung ist jedoch immer noch vorhanden. Jede unterdrückte Warnung kann letztendlich zu einem Laufzeitfehler Ihrer Anwendung führen.

Versuchen Sie, den mit jeder Warnung verbundenen Code zu entfernen oder neu zu schreiben. Das Aktualisieren von Komponenten von Drittanbietern kann ebenfalls hilfreich sein.

Sehen wir uns an, wie wir AOT- und Trimmwarnungen in Docotic.Pdf behoben haben. Einige davon haben Sie bereits im Abschnitt Veröffentlichungswarnungen erhalten gesehen.

Trimmwarnungen von LibLog

Wir haben die LibLog-Bibliothek für die Protokollierung verwendet. LibLog verlässt sich auf Reflektion, um gängige Protokollierungsframeworks zu erkennen und zu verwenden. Es ist von Natur aus nicht mit AOT kompatibel.

Derzeit ist das Paket Microsoft.Extensions.Logging der Standard für die Protokollierung in .NET. Und die LibLog-Entwicklung ist jetzt eingefroren.

Vor diesem Hintergrund haben wir LibLog vollständig aus unserem Code entfernt. Stattdessen haben wir das Add-on Docotic.Pdf.Logging veröffentlicht. Es hängt von den Schnittstellen Microsoft.Extensions.Logging.Abstractions ab. Dadurch wurde die Größe der Kernbibliothek reduziert und alle zugehörigen Trimmwarnungen behoben.

Keine Trimmwarnungen

Ein Debugging-Code im Docotic.Layout-Add-on

Im Docotic.Layout-Add-on verwenden wir Reflektion für internes Debugging. Das führte zu der Warnung IL2075.

Der entsprechende Code ist in der Codebasis vorhanden, aber Clients können ihn nicht über die öffentliche API verwenden. Die Lösung besteht darin, den Code aus der Release-Konfiguration auszuschließen. Er wird jetzt nur in der Debug-Konfiguration verwendet.

AOT-Warnung IL3050 von BouncyCastle

Die BouncyCastle-Bibliothek hilft uns beim Signieren von PDF-Dokumenten. Die folgende Warnung stammt aus dem BouncyCastle-Code:

Org.BouncyCastle.Utilities.Enums.GetEnumValues(Type): Die Verwendung des Mitglieds `System.Enum.GetValues(Type)`, das `RequiresDynamicCodeAttribute` hat, kann die Funktionalität beim AOT-Kompilieren beeinträchtigen. Es ist möglicherweise nicht möglich, zur Laufzeit ein Array des Enumerationstyps zu erstellen. Verwenden Sie stattdessen die Überladung GetValues<TEnum> oder die Methode GetValuesAsUnderlyingType.

BouncyCastle verwendet die Methode Enum.GetValues(Type), die nicht AOT-kompatibel ist.

Die einfachste Lösung wäre, stattdessen die Überladung Enum.GetValues<T>() zu verwenden. Die neueste Version von BouncyCastle verwendet sie bereits. Leider ist diese Überladung nur in .NET 5 oder neuer verfügbar. Dies ist keine Option für .NET Standard 2.0.

Wir haben tiefer gegraben und den BouncyCastle-Code analysiert. Es stellte sich heraus, dass BouncyCastle ihn verwendet, um die Verschleierung von Enumerationskonstanten zu verhindern. Stattdessen haben wir die Verschleierung für entsprechende Enumerationen mithilfe des Attributs [System.Reflection.Obfuscation(Exclude = true)] deaktiviert. Und nicht mehr erforderliche Verwendungen von Enum.GetValues(Type) entfernt.

Ein seltsames Problem im verschleierten Build

Wir verwenden Verschleierung, um Produktions-Builds zu schützen. Überraschenderweise gab die .NET AOT-Bereitstellung für den verschleierten Build ähnliche Warnungen zurück:

<unbekannt>:0: Fehler: Symbol '__GenericLookupFromType_BitMiracle_Docotic_Pdf___4<System___Canon__System___Canon__System___Canon__Int32>_TypeHandle___System___Canon' ist bereits definiert

Solchen Fehlern waren keine IL30##- oder IL2###-Codes zugeordnet. Es war unklar, wie der zugehörige Code zu identifizieren war.

Fehler traten nur in der verschleierten Version auf. Es könnte sich um einen Fehler im Obfuscator handeln. Wir hatten den Obfuscator aktualisiert, aber es waren immer noch Fehler vorhanden.

Wir mussten den Umfang des Problems eingrenzen. Wir haben den folgenden Prozess verwendet, der auf einer binären Suche basiert:

  1. Deaktivieren Sie die Verschleierung für die Hälfte der Namespaces. Überprüfen Sie, ob Fehler auftreten. Fahren Sie fort, bis Sie die Namespaces gefunden haben, die zu den Fehlern geführt haben.
  2. Deaktivieren Sie die Verschleierung für die Hälfte der Typen im Namespace aus Schritt eins. Überprüfen Sie, ob Fehler auftreten. Fahren Sie fort, bis Sie die Typen gefunden haben, die zu den Fehlern geführt haben.
  3. Deaktivieren Sie die Verschleierung für die Hälfte der Mitglieder des Typs aus Schritt zwei. Überprüfen Sie, ob Fehler auftreten. Fahren Sie fort, bis Sie die Mitglieder gefunden haben, die zu den Fehlern geführt haben.
  4. Überprüfen Sie den Code des Mitglieds aus Schritt drei. Kommentieren Sie ungewöhnliche Teile aus und überprüfen Sie, ob Fehler auftreten.

Wir sind bei Schritt eins gelandet 🙂 Nachdem wir die Verschleierung für alle Namespaces deaktiviert hatten, traten immer noch Fehler auf.

Wir haben die generierte Assembly mit ILSpy analysiert. Wir haben einige unerwartete, vom Compiler generierte Typen gefunden. ILSpy hat Verwendungen dieser Typen in folgendem C#-Code angezeigt:

interface X
{
    void f();
}

X obj = ..;
if (obj.f != null)
    ..

Dieser seltsame Code stammt von der Migration von altem C-Code nach C#. Die Bedingung if (obj.f != null) ist völlig überflüssig. Wir haben solche Bedingungen entfernt und die Fehler sind verschwunden.

Verwenden Sie GetCallingAssembly nicht

Wir haben ein weiteres Laufzeitproblem entdeckt. Der Aufruf der Methode LicenseManager.AddLicenseData(string) schlug nach der AOT-Veröffentlichung mit folgendem Fehler fehl:

Assembly.GetCallingAssembly() löst System.PlatformNotSupportedException aus: Vorgang wird auf dieser Plattform nicht unterstützt.

Die Methode Assembly.GetCallingAssembly sollte für Native AOT in .NET 9 implementiert werden. Bis der Fix fertig ist, haben wir unseren Code überarbeitet, um die negativen Auswirkungen zu minimieren. Jetzt verwenden wir die aufrufenden Assembly-Attribute nur zur Validierung der Application-Lizenz. Andere Lizenztypen sind mit AOT kompatibel.

Markieren Sie den Code mit speziellen Attributen

Glücklicherweise konnten wir alle AOT- und Trimmwarnungen in der Docotic.Pdf-Kernbibliothek und den meisten Add-Ons beheben. Aber Sie können möglicherweise nicht den gesamten AOT-inkompatiblen Code neu schreiben.

.NET bietet spezielle Attribute für solche Situationen. Sie markieren die API mit Attributen, um Clients über bekannte AOT-Probleme zu informieren. Benutzer Ihrer API erhalten eine Warnung, wenn sie die markierte Methode aufrufen.

Die wichtigsten Attribute zum Markieren von AOT-inkompatiblem .NET-Code sind:

  • RequiresDynamicCode
  • RequiresUnreferencedCode
  • DynamicallyAccessedMembers

Weitere Informationen zu diesen Attributen finden Sie in den offiziellen Artikeln Einführung in AOT-Warnungen und Vorbereiten von .NET-Bibliotheken für das Trimmen.

Abschluss

Die Native AOT-Bereitstellung ist ein großer Schritt vorwärts in der .NET-Welt. Sie können normalen C#-Code schreiben und eine native Anwendung oder Bibliothek erhalten. Solche Anwendungen sind normalerweise schneller und können ohne installierte .NET-Runtime ausgeführt werden. Sie können sogar veröffentlichte DLLs aus C, Rust oder anderen nicht-.NET-Programmiersprachen verwenden.

Veröffentlichen Sie eine Testanwendung für .NET 8, um AOT-Kompatibilitätsprobleme zu finden. Es gibt auch Roslyn-Analysatoren, aber sie erkennen weniger Probleme.

Die Kernbibliothek Docotic.Pdf ist jetzt mit AOT und Trimming kompatibel. Die folgenden Add-ons sind ebenfalls kompatibel:

  • Layout-Add-on
  • Gdi-Add-on
  • Logging-Add-on

Das HTML-zu-PDF-Add-on enthält immer noch Trimmwarnungen. Dies ist unser nächstes Ziel auf der Native AOT-Roadmap.

Sie können uns gerne Fragen stellen zur nativen AOT- oder PDF-Verarbeitung.