今天我将写一篇关于我如何使用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}
第一步-研究和数据收集:在确保我首先了解报告的问题后,我搜索已知的问题。我发现我们以前见过这种错误。当以下注册表项被删除或损坏时,可能会发生这种情况:HKLMsoftwareMicrosoftMMCSnapInsFX:{ 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:Windowssystem32mmc.exe" "C:Windowssystem32eventvwr.msc" '
你也可以使用dt PEB
0:005> dt nt!_PEB ProcessParameters->CommandLine 000007fffffdb000 ntdll!_PEB +0x020 ProcessParameters : +0x070 CommandLine : _UNICODE_STRING ""C:Windowssystem32mmc.exe" "C:Windowssystem32eventvwr.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:WindowsMicrosoft.NETFrameworkv2.0.50727sos.dll OR 0:011> .load c:WindowsMicrosoft.NETFramework64v2.0.50727sos.dll
但是,一旦您意识到托管调试是必要的,并且您需要SOS扩展的服务,那么最好使用.loadby命令而不是.load。这是因为SOS的版本必须与加载到该过程中的CLR版本相匹配。以下是建议的语法:
0:011 > .loadby sos mscorwks
我总是使用.chain命令验证扩展是否正确加载。
0:011> .chain ... Extension DLL chain: C:WindowsMicrosoft.NETFrameworkv2.0.50727sos.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:WindowsMicrosoft.NETFrameworkv2.0.50727CONFIGmachine.config(on x64 this would be C:WindowsMicrosoft.NETFramework64v2.0.50727CONFIGmachine.config)