共用方式為


收集詳盡的組件載入資訊

從 .NET 5 開始,執行階段可透過 EventPipe 發出具備受控組件載入 詳盡資訊的事件,以此協助診斷組件載入問題。 這些事件 是由 AssemblyLoader 關鍵字 (0x4) 下的 Microsoft-Windows-DotNETRuntime 提供者所發出。

必要條件

注意

dotnet-trace 功能的範圍比收集詳盡的組件載入資訊更廣。 如需 dotnet-trace 使用方式的詳細資訊,請參閱 dotnet-trace

使用組件載入事件收集追蹤

您可使用 dotnet-trace 追蹤現有的流程,或啟動子處理序並從啟動時予以追蹤。

追蹤現有的流程

若要在執行階段啟用組件追蹤事件並針對其收集追蹤,請搭配下列命令使用 dotnet-trace

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

這項命令會收集指定 <pid> 的追蹤,並啟用 Microsoft-Windows-DotNETRuntime 提供者內的 AssemblyLoader 事件。 其結果為 .nettrace 檔案。

用 dotnet-trace 啟動子處理序並從啟動時予以追蹤

有時候從啟動收集處理序追蹤很有用。 針對執行 .NET 5 或更新版本的應用程式,您可使用 dotnet-trace 來進行。

下列命令會在啟動 hello.exe 時以 arg1arg2 作為命令列引數,並從執行階段啟動時收集追蹤:

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

您可按下 [Enter][Ctrl + C] 鍵來停止收集追蹤。這也會關閉 hello.exe

注意

  • 透過 dotnet-trace 啟動 hello.exe 會重新導向其輸入與輸出,根據預設,您將無法在主控台上與之互動。 請用 --show-child-io 參數來與其 stdinstdout 互動。
  • 透過 Ctrl+C 結束工具,或透過 SIGTERM 同時安全地結束工具和子處理序。
  • 如果子處理序在工具之前結束,則工具也會結束,您應可安全地檢視追蹤。

檢視追蹤

收集到的追蹤檔案可透過 PerfView 中的 [事件檢視] 在 Windows 上查看。 所有組件載入事件都會加上 Microsoft-Windows-DotNETRuntime/AssemblyLoader 前置詞。

範例 (在 Windows 上)

此範例運用組件載入擴充點範例。 應用程式試圖載入 MyLibrary 組件,該組件未受應用程式參考,因此需在組件載入擴充點中處理,才能成功載入。

收集追蹤

  1. 使用下載的範例瀏覽至目錄。 使用以下程式碼組建應用程式:

    dotnet build
    
  2. 使用指定應暫停並等候按鍵的引數啟動應用程式。 繼續後,系統會試圖在預設的 AssemblyLoadContext 中載入組件,此時並未進行成功載入所需的處理流程。 瀏覽至輸出目錄並執行以下程式碼:

    AssemblyLoading.exe /d default
    
  3. 找到應用程式的流程識別碼。

    dotnet-trace ps
    

    輸出會列出可用的流程。 例如:

    35832 AssemblyLoading C:\src\AssemblyLoading\bin\Debug\net5.0\AssemblyLoading.exe
    
  4. dotnet-trace 附加至執行中的應用程式。

    dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4 --process-id 35832
    
  5. 在執行應用程式的視窗中,按下任意鍵讓程式繼續執行。 一旦結束應用程式,追蹤就會自動停止。

檢視追蹤

PerfView 中開啟收集到的追蹤,並開啟 [事件檢視]。 將事件清單篩選為 Microsoft-Windows-DotNETRuntime/AssemblyLoader 事件。

PerfView assembly loader filter image

系統會顯示所有啟動追蹤後在應用程式內發生的組件載入活動。 若要為此範例的重點組件 MyLibrary 檢查載入作業,我們可以進一步進行篩選。

組件載入

使用左側的事件清單,將檢視表篩選為 Microsoft-Windows-DotNETRuntime/AssemblyLoader 下的 StartStop 事件。 在檢視表中新增 AssemblyNameActivityIDSuccess 資料行。 篩選為包含 MyLibrary 的事件。

PerfView Start and Stop events image

事件名稱 AssemblyName ActivityID 成功
AssemblyLoader/Start MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ False

您應該會在 Stop 事件上看到一個有 Success=FalseStart/Stop 配對,表示載入作業失敗。 請注意,這兩個事件有相同的活動識別碼。 活動識別碼可用來將其他所有組件載入器事件,篩選為只包含此載入作業的對應項目。

載入意圖的細項

如需載入作業的更多細項,請用左側的事件清單將檢視表篩選為 Microsoft-Windows-DotNETRuntime/AssemblyLoader 下的 ResolutionAttempted 事件。 在檢視表中新增 AssemblyNameStageResult 資料行。 用 Start/Stop 配對的活動識別碼篩選事件。

PerfView ResolutionAttempted events image

事件名稱 AssemblyName 階段 結果
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 叫用處理常式來解析組件。 執行過這所有步驟之後,仍然找不到組件。

擴充點

若要查看所叫用的擴充點,請用左側的事件清單將檢視表篩選為 Microsoft-Windows-DotNETRuntime/AssemblyLoader 下的 AssemblyLoadContextResolvingHandlerInvokedAppDomainAssemblyResolveHandlerInvoked。 在檢視表中新增 AssemblyNameHandlerName 資料行。 用 Start/Stop 配對的活動識別碼篩選事件。

PerfView extension point events image

事件名稱 AssemblyName HandlerName
AssemblyLoader/AssemblyLoadContextResolvingHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAssemblyLoadContextResolving
AssemblyLoader/AppDomainAssemblyResolveHandlerInvoked MyLibrary, Culture=neutral, PublicKeyToken=null OnAppDomainAssemblyResolve

上述事件表示系統針對 AssemblyLoadContext.Resolving 事件叫用了名為 OnAssemblyLoadContextResolving 的處理常式,並針對 AppDomain.AssemblyResolve 事件叫用了名為 OnAppDomainAssemblyResolve 的處理常式。

收集另一個追蹤

用引數執行應用程式,好使 AssemblyLoadContext.Resolving 事件的處理常式載入 MyLibrary 組件。

AssemblyLoading /d default alc-resolving

運用上述步驟收集並開啟另一個 .nettrace 檔案。

再次針對 MyLibrary 篩選 StartStop 事件。 您應該會看到其中有另一組 Start/StopStart/Stop 配對。 內部載入作業代表處理常式在呼叫 AssemblyLoadContext.LoadFromAssemblyPath 時為 AssemblyLoadContext.Resolving 觸發的載入。 這次,您應該會在 Stop 事件中看到 Success=True,表示載入作業已成功。 ResultAssemblyPath 欄位會顯示所產生組件的路徑。

PerfView successful Start and Stop events image

事件名稱 AssemblyName ActivityID 成功 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/ True C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll
AssemblyLoader/Stop MyLibrary, Culture=neutral, PublicKeyToken=null //1/2/ True C:\src\AssemblyLoading\bin\Debug\net5.0\MyLibrary.dll

之後我們可查看活動識別碼來自外部載入的 ResolutionAttempted 事件,判斷組件受到成功解析的步驟。 這次,事件會顯示 AssemblyLoadContextResolvingEvent 階段已經成功。 ResultAssemblyPath 欄位會顯示所產生組件的路徑。

PerfView successful ResolutionAttempted events image

事件名稱 AssemblyName 階段 結果 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 欄位會顯示處理常式傳回的組件路徑。

PerfView successful extension point events image

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

請注意,系統沒有處於 AppDomainAssemblyResolveEvent 階段的 ResolutionAttempted 事件或任何 AppDomainAssemblyResolveHandlerInvoked 事件,因為組件已在觸達引發 AppDomain.AssemblyResolve 事件的載入演算法步驟前成功載入。

另請參閱