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
- .NET 5 SDK oder höhere Versionen
dotnet-trace
-Tool
Hinweis
Der Umfang der dotnet-trace
-Funktionen ist größer als das Sammeln detaillierter Assemblyladeinformationen. Weitere Informationen zur Nutzung von dotnet-trace
finden Sie unter dotnet-trace
.
Erfassen einer Ablaufverfolgung mit Assemblyladeereignissen
Sie können dotnet-trace
verwenden, um einen vorhandenen Prozess zu verfolgen oder einen untergeordneten Prozess zu starten und ihn vom Start aus 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 von dotnet-trace, um einen untergeordneten Prozess zu starten und vom Start aus zu verfolgen
Manchmal kann es nützlich sein, eine Ablaufverfolgung eines Prozesses vom Start zu erfassen. Für Apps, die mit .NET 5 oder höher ausgeführt werden, können Sie hierfür dotnet-trace
verwenden.
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
- Beim Starten von hello.exe über
dotnet-trace
wird die Eingabe und Ausgabe umgeleitet, und Sie können standardmäßig nicht in der Konsole damit interagieren. Verwenden Sie den--show-child-io
-Schalter, um mitstdin
undstdout
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 Ablaufverfolgungsdatei kann unter Windows mithilfe der Ansicht „Ereignisse“ 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, auf die die Anwendung nicht verweist, und die darum in einem Assemblylade-Erweiterungspunkt behandelt werden muss, um erfolgreich geladen zu werden.
Erfassen der Ablaufverfolgung
Navigieren Sie zu dem Verzeichnis, das das heruntergeladene Beispiel enthält. Erstellen Sie die Anwendung mit:
dotnet build
Starten Sie die Anwendung mit Argumenten, die angeben, dass sie anhalten und auf einen Tastendruck warten sollte. Beim Fortsetzen wird sie versuchen, die Assembly im Standard-
AssemblyLoadContext
zu laden – ohne die für ein erfolgreiches Laden erforderliche Handhabung. Navigieren Sie zum Ausgabeverzeichnis, und führen Sie Folgendes aus:AssemblyLoading.exe /d default
Suchen Sie die Prozess-ID der Anwendung.
dotnet-trace ps
In der Ausgabe werden die verfügbaren Prozesse aufgelistet. Beispiel:
35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
Fügen Sie
dotnet-trace
der ausgeführten Anwendung hinzu.dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
Drücken Sie in dem Fenster, in dem die Anwendung ausgeführt wird, eine beliebige Taste, damit das Programm fortgesetzt wird. 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“. Filtern Sie die Ereignisliste nach Microsoft-Windows-DotNETRuntime/AssemblyLoader
-Ereignissen.
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 nach den Start
- und Stop
-Ereignissen unter Microsoft-Windows-DotNETRuntime/AssemblyLoader
mithilfe der Ereignisliste auf der linken Seite. Fügen Sie die Spalten AssemblyName
, ActivityID
und Success
der Ansicht hinzu. Filtern Sie nach Ereignissen, die MyLibrary
enthalten.
Veranstaltungsname | 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 Aktivitäts-ID der beiden Ereignisse identisch ist. Mit der Aktivitäts-ID können aus allen anderen Assemblyladerereignissen die herausgefiltert werden, die diesem Ladevorgang entsprechen.
Aufschlüsselung des Ladeversuchs
Um eine ausführlichere Aufschlüsselung des Ladevorgangs zu erhalten, filtern Sie in der Ansicht mithilfe der Ereignisliste auf der linken Seite die ResolutionAttempted
-Ereignisse unter Microsoft-Windows-DotNETRuntime/AssemblyLoader
heraus. Fügen Sie die Spalten AssemblyName
, Stage
und Result
der Ansicht hinzu. Filtern Sie Ereignisse mit der Aktivitäts-ID aus dem Start
/Stop
-Paar heraus.
Veranstaltungsname | AssemblyName | Phase | 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 zeigen an, dass das Assemblyladerprogramm versucht hat, die Assembly durch Suchen im aktuellen Ladekontext aufzulösen, wobei die standardmäßige Testlogik für verwaltete Anwendungsassemblys ausgeführt und Handler für das AssemblyLoadContext.Resolving-Ereignis und für AppDomain.AssemblyResolve aufgerufen wurden. In allen diesen Schritten wurde die Assembly nicht gefunden.
Erweiterungspunkte
Um anzuzeigen, welche Erweiterungspunkte aufgerufen wurden, filtern Sie die Ansicht mithilfe der Ereignisliste auf der linken Seite nach AssemblyLoadContextResolvingHandlerInvoked
und AppDomainAssemblyResolveHandlerInvoked
unter Microsoft-Windows-DotNETRuntime/AssemblyLoader
. Fügen Sie die Spalten AssemblyName
und HandlerName
der Ansicht hinzu. Filtern Sie Ereignisse mit der Aktivitäts-ID aus dem Start
/Stop
-Paar heraus.
Veranstaltungsname | AssemblyName | HandlerName |
---|---|---|
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAssemblyLoadContextResolving |
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAppDomainAssemblyResolve |
Die obigen Ereignisse zeigen 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.
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
Erfassen und öffnen Sie eine andere .nettrace
-Datei mithilfe der obigen Schritte.
Filtern Sie erneut die Start
- und Stop
-Ereignisse für MyLibrary
. Es sollte ein Start
/Stop
-Paar mit anderem Start
/Stop
angezeigt werden. Der innere Ladevorgang stellt die Ladung dar, die vom Handler für AssemblyLoadContext.Resolving ausgelöst wurde, als AssemblyLoadContext.LoadFromAssemblyPath aufgerufen wurde. Jetzt sollte Success=True
für das Stop
-Ereignis angezeigt werden, um anzugeben, dass der Ladevorgang erfolgreich war. Das ResultAssemblyPath
-Feld zeigt den Pfad der resultierenden Assembly an.
Veranstaltungsname | 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 an, dass die AssemblyLoadContextResolvingEvent
-Phase erfolgreich war. Das ResultAssemblyPath
-Feld zeigt den Pfad der resultierenden Assembly an.
Veranstaltungsname | AssemblyName | Phase | 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 |
AssemblyLoadContextResolvingHandlerInvoked
zeigt, dass der Handler mit dem Namen OnAssemblyLoadContextResolving
aufgerufen wurde. Das ResultAssemblyPath
-Feld zeigt den Pfad der vom Handler zurückgegebenen Assembly an.
Veranstaltungsname | 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.