.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 つの /StopSuccess=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