Freigeben über


Sammeln ausführlicher Informationen zum Laden von Assemblys

Ab .NET 5 kann die Runtime Ereignisse über EventPipe mit detaillierten Informationen über das Laden von verwalteten Assemblys ausgeben, um bei der Diagnose von Problemen beim Laden von Assemblys zu helfen. Diese Ereignisse werden vom Microsoft-Windows-DotNETRuntime Anbieter unter dem AssemblyLoader Schlüsselwort (0x4) ausgegeben.

Voraussetzungen

Hinweis

Der Umfang der dotnet-trace-Funktionen ist größer als das Sammeln detaillierter Assemblyladeinformationen. Weitere Informationen zur Verwendung von dotnet-trace, finden Sie unter dotnet-trace.

Erfassen einer Ablaufverfolgung mit Assemblyladeereignissen

Sie können verwenden dotnet-trace , um einen vorhandenen Prozess nachzuverfolgen oder einen untergeordneten Prozess zu starten und ihn vom Start zu verfolgen.

Verfolgen eines vorhandenen Prozesses

Verwenden Sie dotnet-trace mit dem folgenden Befehl, um Assemblyladeereignisse in der Runtime zu aktivieren und eine Ablaufverfolgung zu erfassen:

dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id <pid>

Mit diesem Befehl wird eine Ablaufverfolgung der angegebenen <pid> erfasst, wodurch die AssemblyLoader-Ereignisse im Microsoft-Windows-DotNETRuntime-Anbieter aktiviert werden. Das Ergebnis ist eine .nettrace Datei.

Verwenden Sie dotnet-trace, um einen untergeordneten Prozess zu starten und ihn vom Start zu nachverfolgen.

Manchmal kann es nützlich sein, eine Ablaufverfolgung eines Prozesses vom Start zu erfassen. Für Apps mit .NET 5 oder höher können Sie dies verwenden dotnet-trace .

Mit dem folgenden Befehl wird hello.exe mit arg1 und arg2 als Befehlszeilenargumenten gestartet, und der Ablauf wird vom Start der Runtime verfolgt:

dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 -- hello.exe arg1 arg2

Sie können die Ablaufverfolgungssammlung beenden, indem Sie die Eingabetaste oder STRG + C drücken. Dadurch wird auch hello.exe geschlossen.

Hinweis

  • Das Starten von hello.exe über dotnet-trace umleitet seine Eingabe und Ausgabe, und Sie können standardmäßig nicht mit ihm auf der Konsole interagieren. Verwenden Sie den --show-child-io Schalter, um mit seinem stdin und stdout zu interagieren.
  • Wenn Sie das Tool über STRG+C oder SIGTERM beenden, wird sowohl das Tool als auch der untergeordnete Prozess sicher beendet.
  • Wenn der untergeordnete Prozess vor dem Tool beendet wird, wird das Tool ebenfalls beendet, und die Ablaufverfolgung sollte sicher angezeigt werden können.

Anzeigen einer Ablaufverfolgung

Die erfasste Protokolldatei kann unter Windows mithilfe der Ereignisansicht in PerfView angezeigt werden. Allen Assemblyladeereignissen wird Microsoft-Windows-DotNETRuntime/AssemblyLoader vorangestellt.

Beispiel (unter Windows)

Dies ist ein Beispiel mit Assemblylade-Erweiterungspunkten. Die Anwendung versucht, eine Assembly MyLibrary zu laden – eine Assembly, auf die nicht von der Anwendung verwiesen wird, und die daher in einem Assemblyladeerweiterungspunkt bearbeitet werden muss, um erfolgreich geladen zu werden.

Erfassen der Ablaufverfolgung

  1. Navigieren Sie zum Verzeichnis mit dem heruntergeladenen Beispiel. Erstellen Sie die Anwendung mit:

    dotnet build
    
  2. Starten Sie die Anwendung mit Argumenten, die angeben, dass sie angehalten werden soll, und warten Sie auf ein Drücken einer Taste. Beim Fortsetzen wird versucht, die Assembly in der Standardeinstellung AssemblyLoadContext zu laden – ohne die Handhabung, die für ein erfolgreiches Laden erforderlich ist. Navigieren Sie zum Ausgabeverzeichnis, und führen Sie Folgendes aus:

    AssemblyLoading.exe /d default
    
  3. Suchen Sie die Prozess-ID der Anwendung.

    dotnet-trace ps
    

    Die Ausgabe listet die verfügbaren Prozesse auf. Beispiel:

    35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
    
  4. Verbinden Sie dotnet-trace mit der laufenden Anwendung.

    dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
    
  5. Drücken Sie im Fenster, in dem die Anwendung ausgeführt wird, eine beliebige Taste, damit das Programm fortgesetzt werden kann. Die Ablaufverfolgung wird automatisch beendet, nachdem die Anwendung beendet wurde.

Anzeigen der Ablaufverfolgung

Öffnen Sie die erfasste Ablaufverfolgung in PerfView, und öffnen Sie die Ansicht „Ereignisse“. Filtert die Ereignisliste auf Microsoft-Windows-DotNETRuntime/AssemblyLoader Ereignisse.

Bild zu PerfView-Assemblyladerfilter

Alle Assemblyladungen, die nach dem Start der Ablaufverfolgung in der Anwendung aufgetreten sind, werden angezeigt. Um den Ladevorgang für die Assembly zu überprüfen, die für dieses Beispiel von Interesse ist – MyLibrary – können wir weitere Filterungen durchführen.

Assemblyladungen

Filtern Sie die Ansicht auf die Ereignisse Start und Stop unter Microsoft-Windows-DotNETRuntime/AssemblyLoader mithilfe der Ereignisliste auf der linken Seite. Fügen Sie die Spalten AssemblyName, ActivityIDund Success der Ansicht hinzu. Filtern Sie nach Ereignissen, die MyLibrary enthalten.

Bild zu den PerfView-Start- und -Stoppereignissen

Ereignisname AssemblyName Aktivitäts-ID Erfolg
AssemblyLoader/Start MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ Falsch

Es sollte ein Start/Stop-Paar mit Success=False für das Stop-Ereignis angezeigt werden, das angibt, dass beim Ladevorgang ein Fehler aufgetreten ist. Beachten Sie, dass die beiden Ereignisse dieselbe Aktivitäts-ID aufweisen. Die Aktivitäts-ID kann verwendet werden, um alle anderen Assemblyladeereignisse auf nur diejenigen zu filtern, die diesem Ladevorgang entsprechen.

Aufschlüsselung des Ladeversuchs

Für eine detailliertere Aufschlüsselung des Ladevorgangs filtern Sie die Ansicht mithilfe der Ereignisliste auf der linken Seite auf die ResolutionAttempted Ereignisse unter Microsoft-Windows-DotNETRuntime/AssemblyLoader. Fügen Sie die Spalten AssemblyName, Stageund Result der Ansicht hinzu. Filtern Sie nach Ereignissen mit der Aktivitäts-ID aus dem Start/Stop Paar.

Bild zu PerfView-ResolutionAttempted-Ereignissen

Ereignisname AssemblyName Etappe Ergebnis
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null FindInLoadContext AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null ApplicationAssemblies AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null AssemblyLoadContextResolvingEvent AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null AppDomainAssemblyResolveEvent AssemblyNotFound

Die obigen Ereignisse geben an, dass das Assemblyladeprogramm versucht hat, die Assembly aufzulösen, indem im aktuellen Ladekontext nachgeschaut wird, die Standard-Probinglogik für verwaltete Anwendungsassemblys ausgeführt wird, Handler für das AssemblyLoadContext.Resolving-Ereignis aufgerufen werden und Handler für das AppDomain.AssemblyResolve-Ereignis aufgerufen werden. In allen diesen Schritten wurde die Assembly nicht gefunden.

Erweiterungspunkte

Um zu sehen, welche Erweiterungspunkte aufgerufen wurden, filtern Sie die Ansicht zu AssemblyLoadContextResolvingHandlerInvoked und AppDomainAssemblyResolveHandlerInvoked unter Microsoft-Windows-DotNETRuntime/AssemblyLoader mithilfe der Ereignisliste auf der linken Seite. Fügen Sie die Spalten AssemblyName und HandlerName der Ansicht hinzu. Filtern Sie nach Ereignissen mit der Aktivitäts-ID aus dem Start/Stop Paar.

Bild zu PerfView-Erweiterungspunktereignissen

Ereignisname AssemblyName HandlerName
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAppDomainAssemblyResolve

Die obigen Ereignisse geben an, dass ein Handler mit dem Namen OnAssemblyLoadContextResolving für das AssemblyLoadContext.Resolving Ereignis aufgerufen wurde und ein Handler mit dem Namen OnAppDomainAssemblyResolve für das AppDomain.AssemblyResolve Ereignis aufgerufen wurde.

Erfassen einer anderen Ablaufverfolgung

Führen Sie die Anwendung mit Argumenten aus, sodass der Handler für das AssemblyLoadContext.Resolving Ereignis die MyLibrary Assembly lädt.

AssemblyLoading /d default alc-resolving

Sammeln und öffnen Sie eine andere .nettrace Datei mithilfe der oben beschriebenen Schritte.

Filtern Sie erneut die Start- und Stop-Ereignisse für MyLibrary. Du solltest ein Start/Stop-Paar sehen, mit einem anderen Start/Stop dazwischen. Der innere Ladevorgang stellt die Ladung dar, die vom Handler für AssemblyLoadContext.Resolving ausgelöst wurde, als AssemblyLoadContext.LoadFromAssemblyPath aufgerufen wurde. Dieses Mal sollten Sie Success=True im Stop Ereignis sehen, was darauf hinweist, dass der Ladevorgang erfolgreich war. Das ResultAssemblyPath Feld zeigt den Pfad der resultierenden Assembly an.

Bild zu den erfolgreichen PerfView-Start- und -Stoppereignissen

Ereignisname AssemblyName Aktivitäts-ID Erfolg ResultAssemblyPath
AssemblyLoader/Start MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/
AssemblyLoader/Start MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //1/2/1/
AssemblyLoader/Stop MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //1/2/1/ Richtig C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ Richtig C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Wir können dann die ResolutionAttempted-Ereignisse mit der Aktivitäts-ID aus der äußeren Ladung betrachten, um den Schritt zu ermitteln, in dem die Assembly erfolgreich aufgelöst wurde. Dieses Mal zeigen die Ereignisse, dass die AssemblyLoadContextResolvingEvent Phase erfolgreich war. Das ResultAssemblyPath Feld zeigt den Pfad der resultierenden Assembly an.

Bild zu erfolgreichen PerfView-ResolutionAttempted-Ereignissen

Ereignisname AssemblyName Etappe Ergebnis ResultAssemblyPath
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null FindInLoadContext AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null ApplicationAssemblies AssemblyNotFound
AssemblyLoader/ResolutionAttempted MyLibrary, Culture=neutral, PublicKeyToken=null AssemblyLoadContextResolvingEvent Success C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Beim Betrachten von AssemblyLoadContextResolvingHandlerInvoked Ereignissen wird gezeigt, dass der genannte OnAssemblyLoadContextResolving handler aufgerufen wurde. Das ResultAssemblyPath Feld zeigt den Pfad der Assembly an, die vom Handler zurückgegeben wird.

Bild von erfolgreichen Erweiterungspunktereignissen in PerfView

Ereignisname AssemblyName HandlerName ResultAssemblyPath
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

Beachten Sie, dass kein ResolutionAttempted-Ereignis mit der AppDomainAssemblyResolveEvent-Phase oder AppDomainAssemblyResolveHandlerInvoked-Ereignisse mehr vorhanden sind, da die Assembly erfolgreich geladen wurde, bevor der Schritt des Ladealgorithmus erreicht wurde, der das AppDomain.AssemblyResolve-Ereignis auslöst.

Siehe auch