.NET 5 以降では、ランタイムは、アセンブリの読み込み問題の診断に役立つEventPipe
関する詳細情報を含むを介してイベントを生成できます。 これらのイベントは、Microsoft-Windows-DotNETRuntime
キーワード (AssemblyLoader
) の下で0x4
プロバイダーによって生成されます。
[前提条件]
- .NET 5 SDK 以降のバージョン
-
dotnet-trace
ツール
注
dotnet-trace
機能のスコープは、詳細なアセンブリ読み込み情報を収集するよりも大きくなります。
dotnet-trace
の使用方法の詳細については、dotnet-trace
を参照してください。
アセンブリ読み込みイベントを使用してトレースを収集する
dotnet-trace
を使用して、既存のプロセスをトレースしたり、子プロセスを起動して起動時からトレースしたりできます。
既存のプロセスをトレースする
ランタイムでアセンブリの読み込みイベントを有効にし、それらのトレースを収集するには、次のコマンドで dotnet-trace
を使用します。
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id <pid>
このコマンドは、指定した<pid>
のトレースを収集し、AssemblyLoader
プロバイダーでMicrosoft-Windows-DotNETRuntime
イベントを有効にします。 結果は .nettrace
ファイルになります。
dotnet-trace を使用して子プロセスを起動し、スタートアップからトレースする
場合によっては、プロセスのトレースをそのスタートアップから収集すると便利なことがあります。 .NET 5 以降を実行しているアプリの場合は、 dotnet-trace
を使用してこれを行うことができます。
次のコマンドは hello.exe を、コマンドライン引数として arg1
と arg2
を指定して起動し、実行時の起動プロセスからトレースを収集します。
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 -- hello.exe arg1 arg2
Enter キーまたは + C キーを押すと、トレースの収集を停止できます。これにより、hello.exeも閉じます。
注
-
を使用して
dotnet-trace
を起動すると、その入力と出力がリダイレクトされ、既定ではコンソールで操作できなくなります。--show-child-io
スイッチを使用して、そのstdin
とstdout
を操作します。 -
+
C または
SIGTERM
を使用してツールを終了すると、ツールと子プロセスの両方が安全に終了します。 - ツールの前に子プロセスが終了すると、ツールも終了し、トレースを安全に表示できます。
トレースを表示する
収集されたトレース ファイルは、 PerfView の [イベント] ビューを使用して Windows で表示できます。 すべてのアセンブリ読み込みイベントには、プレフィックスとして Microsoft-Windows-DotNETRuntime/AssemblyLoader
が付けられます。
例 (Windows の場合)
この例では、 アセンブリの読み込み拡張ポイントのサンプルを使用します。 アプリケーションはアセンブリ MyLibrary
を読み込もうとします。アセンブリはアプリケーションによって参照されていないため、アセンブリ読み込み拡張機能ポイントでの処理が正常に読み込まれる必要があります。
トレースを収集する
ダウンロードしたサンプルを含むディレクトリに移動します。 次の方法でアプリケーションをビルドします。
dotnet build
キーを押すのを待って、一時停止する必要があることを示す引数を指定してアプリケーションを起動します。 再開すると、既定の
AssemblyLoadContext
でアセンブリの読み込みが試行されます。読み込みを成功させるために必要な処理は必要ありません。 出力ディレクトリに移動し、次のコマンドを実行します。AssemblyLoading.exe /d default
アプリケーションのプロセス ID を見つけます。
dotnet-trace ps
出力には、使用可能なプロセスが一覧表示されます。 例えば次が挙げられます。
35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
実行中のアプリケーションに
dotnet-trace
をアタッチします。dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
アプリケーションを実行しているウィンドウで、任意のキーを押してプログラムを続行します。 トレースは、アプリケーションが終了すると自動的に停止します。
トレースを表示する
収集したトレースを PerfView で開き、[イベント] ビューを開きます。 イベント一覧をMicrosoft-Windows-DotNETRuntime/AssemblyLoader
イベントに絞り込みます。
トレースの開始後にアプリケーションで発生したすべてのアセンブリ読み込みが表示されます。 この例の目的のアセンブリの読み込み操作 ( MyLibrary
) を調べるには、さらにフィルター処理を行うことができます。
アセンブリの負荷
左側のイベント リストを使用して、Start
の下にあるStop
およびMicrosoft-Windows-DotNETRuntime/AssemblyLoader
のイベントにビューをフィルター処理します。 列 AssemblyName
、 ActivityID
、および Success
をビューに追加します。
MyLibrary
を含むイベントをフィルターする。
イベント名 | アセンブリ名 | アクティビティID | 成功 |
---|---|---|---|
AssemblyLoader/Start |
MyLibrary, Culture=neutral, PublicKeyToken=null |
//1/2/ | |
AssemblyLoader/Stop |
MyLibrary, Culture=neutral, PublicKeyToken=null |
//1/2/ | いいえ |
Start
イベントに 1 つの /Stop
Success=False
ペアと Stop
があります。これは、読み込み操作が失敗したことを示します。 2 つのイベントのアクティビティ ID は同じであることに注意してください。 アクティビティ ID を使用すると、他のすべてのアセンブリ ローダー イベントをフィルター処理して、この読み込み操作に対応するイベントのみをフィルター処理できます。
読み込み試行の内訳
読み込み操作の詳細な内訳については、左側のイベント一覧を使用し、ResolutionAttempted
の下にある Microsoft-Windows-DotNETRuntime/AssemblyLoader
にビューをフィルター処理してください。 列 AssemblyName
、 Stage
、および Result
をビューに追加します。
Start
/
Stop
ペアのアクティビティ ID を持つイベントをフィルタリングします。
イベント名 | アセンブリ名 | 段階 | 結果 |
---|---|---|---|
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 |
上記のイベントは、アセンブリ ローダーが現在の読み込みコンテキストを調べて、マネージド アプリケーション アセンブリの既定のプローブ ロジックを実行し、 AssemblyLoadContext.Resolving イベントのハンドラーを呼び出し、 AppDomain.AssemblyResolveのハンドラーを呼び出すことによってアセンブリを解決しようとしたことを示しています。 これらのすべての手順で、アセンブリが見つかりませんでした。
拡張点
呼び出された拡張ポイントを確認するには、左側のイベント リストを使用して、ビューをAssemblyLoadContextResolvingHandlerInvoked
の下にあるAppDomainAssemblyResolveHandlerInvoked
およびMicrosoft-Windows-DotNETRuntime/AssemblyLoader
にフィルターします。 ビューにAssemblyName
列とHandlerName
列を追加します。
Start
/
Stop
ペアのアクティビティ ID を持つイベントをフィルタリングします。
イベント名 | アセンブリ名 | HandlerName |
---|---|---|
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAssemblyLoadContextResolving |
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAppDomainAssemblyResolve |
上記のイベントは、OnAssemblyLoadContextResolving
イベントに対して AssemblyLoadContext.Resolving という名前のハンドラーが呼び出され、OnAppDomainAssemblyResolve
イベントに対して AppDomain.AssemblyResolve という名前のハンドラーが呼び出されたことを示しています。
別のトレースを収集する
AssemblyLoadContext.Resolving イベントのハンドラーが MyLibrary
アセンブリを読み込むような引数を指定してアプリケーションを実行します。
AssemblyLoading /d default alc-resolving
.nettrace
を使用して、別の ファイルを収集して開きます。
フィルター処理して Start
の Stop
および MyLibrary
イベントをもう一度表示します。
Start
/
Stop
のペアとその間に別の Start
/Stop
があります。 内部読み込み操作は、AssemblyLoadContext.Resolvingが呼び出された時、AssemblyLoadContext.LoadFromAssemblyPathのハンドラーによってトリガーされた読み込みを表します。 今回は、読み込み操作が成功したことを示すSuccess=True
イベントのStop
が表示されます。
ResultAssemblyPath
フィールドには、結果のアセンブリのパスが表示されます。
イベント名 | アセンブリ名 | アクティビティID | 成功 | 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/ | 正しい | C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll |
AssemblyLoader/Stop |
MyLibrary, Culture=neutral, PublicKeyToken=null |
//1/2/ | 正しい | C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll |
その後、外部ロードのアクティビティ ID を持つ ResolutionAttempted
イベントを調べて、アセンブリが正常に解決されたステップを特定できます。 今回は、 AssemblyLoadContextResolvingEvent
ステージが成功したことがイベントに表示されます。
ResultAssemblyPath
フィールドには、結果のアセンブリのパスが表示されます。
イベント名 | アセンブリ名 | 段階 | 結果 | 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
イベントを見ると、OnAssemblyLoadContextResolving
という名前のハンドラーが呼び出されたことが示されます。
ResultAssemblyPath
フィールドには、ハンドラーによって返されるアセンブリのパスが表示されます。
イベント名 | アセンブリ名 | HandlerName | ResultAssemblyPath |
---|---|---|---|
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked |
MyLibrary, Culture=neutral, PublicKeyToken=null |
OnAssemblyLoadContextResolving |
C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll |
ResolutionAttempted
イベントを発生させる読み込みアルゴリズムのステップに到達する前にアセンブリが正常に読み込まれたため、AppDomainAssemblyResolveEvent
ステージまたはAppDomainAssemblyResolveHandlerInvoked
イベントを含むAppDomain.AssemblyResolve イベントはなくなりました。
こちらも参照ください
.NET