今天我將寫一篇關於我如何使用SOS.Net框架調試擴展(和!analyze-v)以輕松解決.NETFramework異常。此異常阻止事件查看器正確顯示。事件查看器返回了一個錯誤,該錯誤提供了有關導致該問題的實際原因的很少信息。在本例中,我將演示如何使用windbg來獲取有關出錯的信息。我不必對此問題執行實時調試。相反,我使用進程轉儲來獲取與根本原因相關的非常精確的信息,這些信息由調試器返回。然后我可以使用進程監視器來識別需要檢查的文件。這些行動使我找到了問題的根源,很容易就得到了糾正。
報告的問題:打開時遇到以下錯誤事件vwr.msc(事件查看器)在Windows 2008 Server系統上:
"MMC could not create the snap-in." MMC could not create the snap-in. The snap-in might not have been installed correctly Name: Event Viewer CLSID: FX:{b05566ad-fe9c-4363-be05-7a4cbb7cb510}
第一步-研究和數據收集:在確保我首先了解報告的問題后,我搜索已知的問題。我發現我們以前見過這種錯誤。當以下注冊表項被刪除或損壞時,可能會發生這種情況:HKLM\software\Microsoft\MMC\SnapIns\FX:{ b05566ad-fe9c-4363-be05-7a4cbb7cb510}
我讓客戶導出這個密鑰,發現它沒有任何損壞。我核實了所有的數據都和預期的一樣
接下來,內存轉儲mmc.exe收集過程。這個mmc.exe進程用於托管事件vwr.msc管理單元。使用內置的windows2008服務器“Windows任務管理器”功能:“創建轉儲文件”可以輕松獲得這一點。如果您的系統上有多個mmc控制台實例正在執行,您可以使用任務管理器上下文菜單快捷方式“切換到”和“轉到進程”來幫助您識別正確的實例。
注意:在事件vwr.msc. 這個日志文件后來被證明對解決這個問題非常有幫助(如下所示)。可從以下URL獲取進程監視器:http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
現在讓我們來看看調試。
首先,我將Windows資源管理器導航到轉儲文件的位置,然后雙擊它以在中打開它windbg.exe.
它是在windbg中打開的,因為我以前運行過命令windbg-IA,它將.dmp文件與windbg相關聯。您可以在調試工具附帶的幫助文件中閱讀有關windbg中命令行選項的更多信息。
我注意到調試器加載轉儲文件后的以下輸出:
This dump file has an exception of interest stored in it. The stored exception information can be accessed via .ecxr. (ff8.a2c): CLR exception - code e0434f4d (first/second chance not available)
接下來,我想確保我的符號路徑設置正確。我可以用.sympath命令設置它:
0:011> .sympath SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols Expanded Symbol search path is: srv*c:\websymbols*http://msdl.microsoft.com/download/symbols 0:011> .sympath Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols Expanded Symbol search path is: srv*c:\websymbols*http://msdl.microsoft.com/download/symbols
但是,如果您的目標是簡單地指向默認的符號服務器,.symfix是一個非常好的快捷方式。它可以防止用戶不得不嘗試記住URL。語法如下:
0:011> .symfix c:\websymbols 0:011> .sympath Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
為了確保我不會浪費時間查看錯誤的數據,我執行了一個快速檢查,以確保我們收集了所請求的管理單元的轉儲。
0:005> !peb PEB at 000007fffffdb000 .... CommandLine: '"C:\Windows\system32\mmc.exe" "C:\Windows\system32\eventvwr.msc" '
你也可以使用dt PEB
0:005> dt nt!_PEB ProcessParameters->CommandLine 000007fffffdb000 ntdll!_PEB +0x020 ProcessParameters : +0x070 CommandLine : _UNICODE_STRING ""C:\Windows\system32\mmc.exe" "C:\Windows\system32\eventvwr.msc" "
接下來,我轉儲了這個進程中的所有線程,發現下面的線程包含一個引發.NETFramework異常的堆棧
0:011> ~* kL ... (ommitted the non-relevent threads) # 11 Id: ff8.a2c Suspend: 1 Teb: 7ffd3000 Unfrozen ChildEBP RetAddr 0691f03c 7343a91c kernel32!RaiseException+0x58 0691f09c 7343d81a mscorwks!RaiseTheExceptionInternalOnly+0x2a8 *** WARNING: Unable to verify checksum for MMCEx.ni.dll 0691f140 6bfe0b5a mscorwks!JIT_Rethrow+0xbf *** WARNING: Unable to verify checksum for mscorlib.ni.dll 0691f1e8 69926cf6 MMCEx_ni+0xd0b5a 0691f1f4 6993019f mscorlib_ni+0x216cf6 0691f208 69926c74 mscorlib_ni+0x22019f 0691f220 733d1b4c mscorlib_ni+0x216c74 0691f230 733e21b1 mscorwks!CallDescrWorker+0x33 0691f2b0 733f6501 mscorwks!CallDescrWorkerWithHandler+0xa3 0691f3e8 733f6534 mscorwks!MethodDesc::CallDescr+0x19c 0691f404 733f6552 mscorwks!MethodDesc::CallTargetWorker+0x1f 0691f41c 7349d803 mscorwks!MethodDescCallSite::CallWithValueTypes+0x1a 0691f604 733f845f mscorwks!ThreadNative::KickOffThread_Worker+0x192 0691f618 733f83fb mscorwks!Thread::DoADCallBack+0x32a 0691f6ac 733f8321 mscorwks!Thread::ShouldChangeAbortToUnload+0xe3 0691f6e8 733f84ad mscorwks!Thread::ShouldChangeAbortToUnload+0x30a 0691f710 7349d5d4 mscorwks!Thread::ShouldChangeAbortToUnload+0x33e 6. Out of curiosity, I also ran the Get Last Error command 0:011> !gle LastErrorValue: (Win32) 0 (0) - The operation completed successfully. LastStatusValue: (NTSTATUS) 0 - STATUS_WAIT_0
之后,我運行analyze-v來查看調試器將提供哪些有用的信息。調試器確實輸出了異常信息,但通知我需要改用x86調試器。
0:011> !analyze -v ... EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 771a42eb (kernel32!RaiseException+0x00000058) ExceptionCode: e0434f4d (CLR exception) ExceptionFlags: 00000001 NumberParameters: 1 Parameter[0]: 80131604 MANAGED_BITNESS_MISMATCH: Managed code needs matching platform of sos.dll for proper analysis. Use 'x86' debugger. FAULTING_THREAD: 00000a2c PRIMARY_PROBLEM_CLASS: CLR_EXCEPTION
我啟動了x86調試器並加載了適當版本的SOS.Net框架調試器擴展。此擴展隨.Net一起隨操作系統一起提供框架。開大多數情況下,我會通過使用以下語法啟動加載擴展:
0:011> .load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll OR 0:011> .load c:\Windows\Microsoft.NET\Framework64\v2.0.50727\sos.dll
但是,一旦您意識到托管調試是必要的,並且您需要SOS擴展的服務,那么最好使用.loadby命令而不是.load。這是因為SOS的版本必須與加載到該過程中的CLR版本相匹配。以下是建議的語法:
0:011 > .loadby sos mscorwks
我總是使用.chain命令驗證擴展是否正確加載。
0:011> .chain ... Extension DLL chain: C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll: image 2.0.50727.1434, API 1.0.0, built Wed Dec 05 22:42:38 2007
執行!help打印了以下關於SOS擴展的有用信息sos.dll處於鏈輸出的頂端:
0:011> !help ------------------------------------------------------------------------------- SOS is a debugger extension DLL designed to aid in the debugging of managed programs. Functions are listed by category, then roughly in order of importance. Shortcut names for popular functions are listed in parenthesis. Type "!help <functionname>" for detailed info on that function. Object Inspection Examining code and stacks ----------------------------- ----------------------------- DumpObj (do) Threads DumpArray (da) CLRStack DumpStackObjects (dso) IP2MD DumpHeap U DumpVC DumpStack GCRoot EEStack ObjSize GCInfo FinalizeQueue EHInfo PrintException (pe) COMState TraverseHeap BPMD
使用由調試器在打開轉儲時顯示的異常地址,以及上面列出的!pe命令,我獲得了有關異常的更多信息:
0:011> !pe 771a42eb Invalid object There are nested exceptions on this thread. Run with -nested for details 0:011> !pe -nested 771a42eb Invalid object Nested exception ------------------------------------------------------------- Exception object: 040a676c Exception type: System.Reflection.TargetInvocationException Message: Exception has been thrown by the target of an invocation. InnerException: System.Reflection.TargetInvocationException, use !PrintException 040a6a20 to see more StackTrace (generated): SP IP Function StackTraceString: <none> HResult: 80131604 0:011> !PrintException 040a6a20 Exception object: 040a6a20 Exception type: System.Reflection.TargetInvocationException Message: Exception has been thrown by the target of an invocation. InnerException: System.Configuration.ConfigurationErrorsException, use !PrintException 040a6cf8 to see more StackTrace (generated): <none> StackTraceString: <none> HResult: 80131604 There are nested exceptions on this thread. Run with -nested for details 0:011> !PrintException 040a6cf8 Exception object: 040a6cf8 Exception type: System.Configuration.ConfigurationErrorsException Message: Configuration system failed to initialize InnerException: System.Configuration.ConfigurationErrorsException, use !PrintException 040a7174 to see more StackTrace (generated): <none> StackTraceString: <none> HResult: 80131902 There are nested exceptions on this thread. Run with -nested for details 0:011> !PrintException 040a7174 Exception object: 040a7174 Exception type: System.Configuration.ConfigurationErrorsException Message: Unrecognized configuration section system.web/myInvalidData InnerException: <none> StackTrace (generated): <none> StackTraceString: <none> HResult: 80131902 There are nested exceptions on this thread. Run with -nested for details
根據上面列出的異常信息,.Net Framework配置部分,System.web,其中包含名為MyInvalidDataIn的無效配置節。我再次針對轉儲 !analyze-v(現在我已經加載了x86調試器)並發現了這一點!analyze-v將加載sos.dll延長甚至運行!pe自動擴展。然后它也會自動為我顯示異常記錄信息。另外,請注意下面列出的線程!analyze-v與我之前檢查的線程匹配。
0:011> !analyze -v ... EXCEPTION_MESSAGE: Unrecognized configuration section system.web/myInvalidData. MANAGED_OBJECT_NAME: System.Configuration.ConfigurationErrorsException FAULTING_THREAD: 00000a2c 0:011> ~ 0 Id: ff8.c84 Suspend: 1 Teb: 7ffdf000 Unfrozen 1 Id: ff8.96c Suspend: 1 Teb: 7ffde000 Unfrozen 2 Id: ff8.d10 Suspend: 1 Teb: 7ffdd000 Unfrozen 3 Id: ff8.d94 Suspend: 1 Teb: 7ffdc000 Unfrozen 4 Id: ff8.a14 Suspend: 1 Teb: 7ffda000 Unfrozen 5 Id: ff8.fbc Suspend: 1 Teb: 7ffd9000 Unfrozen 6 Id: ff8.f88 Suspend: 1 Teb: 7ffd8000 Unfrozen 7 Id: ff8.a64 Suspend: 1 Teb: 7ffd6000 Unfrozen 8 Id: ff8.bf8 Suspend: 1 Teb: 7ffd5000 Unfrozen 9 Id: ff8.d24 Suspend: 1 Teb: 7ffd4000 Unfrozen 10 Id: ff8.ff0 Suspend: 1 Teb: 7ffd7000 Unfrozen . 11 Id: ff8.a2c Suspend: 1 Teb: 7ffd3000 Unfrozen
在這一點上,我對識別這個無法識別的配置的源很感興趣。我沒有讓我們的.Net支持團隊參與。通過快速查看返回的一些點擊,我發現其他人在他們自己的應用程序中遇到了這個異常。這是由於.Net中使用的各種.config文件中的無效條目造成的。通過查看帖子,可以看到不同的配置文件名和路徑。
所以,我打開了進程監視器日志文件來查看我們從哪些配置文件中讀取數據。我添加了篩選條件來匹配來自mmc.exe文件進程中,異常數據中列出的出錯_線程的TID、包含.config的路徑數據以及成功的狀態結果。最好盡可能具體。
我發現我們從.net Framework全局配置文件中反復讀取大量設置:c:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config(on x64 this would be C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\machine.config)