大家应该知道 .NET异常 本质上就是一个 Object 对象,也就是说只要你执行了 new XXException() 语句,那么它就会分配到 GC Heap 上。
这也就意味着,如果你有一个进程的dump文件,那你就可以从dump中导出程序最近都抛了什么异常,换句话说只要这些异常没有被 GC 回收,你都可以给它找出来。
实现起来很简单,只要在 windbg 中输入如下命令即可。
- 0:015> !dumpheap -type Exception
- ------------------------------
- Heap 0
- Address MT Size
- 02ea6b0c 79330a80 72
- 02ea75f0 7930eab4 76
- …
- 06f57aa4 7930eab4 76
- 06f5829c 7930eab4 76
- 06f58a94 7930eab4 76
- 06f5928c 7930eab4 76
- 06f59a84 7930eab4 76
- 06f5a27c 7930eab4 76
- 06f5aa74 7930eab4 76
- 06f5b26c 7930eab4 76
- 06f5ba64 7930eab4 76
- 06f5c25c 7930eab4 76
- 06f5ca54 7930eab4 76
- 06f5d24c 7930eab4 76
- total 319 objects
- ------------------------------
- total 656 objects
- Statistics:
- MT Count TotalSize Class Name
- 79333dc0 1 12 System.Text.DecoderExceptionFallback
- 79333d7c 1 12 System.Text.EncoderExceptionFallback
- 793172f8 2 64 System.UnhandledExceptionEventHandler
- 79330c30 1 72 System.ExecutionEngineException
- 79330ba0 1 72 System.StackOverflowException
- 79330b10 1 72 System.OutOfMemoryException
- 79330a80 1 72 System.Exception
- 79330cc0 2 144 System.Threading.ThreadAbortException
- 7930eab4 646 49096 System.IO.DirectoryNotFoundException
- Total 656 objects
如果你想看某一个具体异常的详细信息,可以使用命令 !pe 02ea6b0c 。
- !pe 02ea6b0c
- Exception object: 02ea6b0c
- Exception type: System.Exception
- Message: The email entered is not a valid email address
- InnerException: <none>
- StackTrace (generated):
- SP IP Function
- 024AF2C8 0FE3125E App_Code_da2s7oyo!BuggyMail.IsValidEmailAddress(System.String)+0x76
- 024AF2E8 0FE31192 App_Code_da2s7oyo!BuggyMail.SendEmail(System.String, System.String)+0x4a
- StackTraceString: <none>
- HResult: 80131500
- There are nested exceptions on this thread. Run with -nested for details
那现在问题来了,我想看所有异常的详细信息怎么办呢?人肉一个一个的用 !pe 命令去执行,那将会多恶心。。。所以友好的方式就是写脚本去提速,这里我使用 .foreach 命令。
- .foreach (ex {!dumpheap -type Exception -short}){.echo "********************************";!pe ${ex} }
上面我用了一个 -short 参数,目的就是只输出 address 地址方便脚本遍历,然后将迭代项送入 !pe ,输出结果如下:
- 0:015> .foreach (ex {!dumpheap -type Exception -short}){.echo "********************************";!pe ${ex} }
- ********************************
- Exception object: 02ea6b0c
- Exception type: System.Exception
- Message: The email entered is not a valid email address
- InnerException: <none>
- StackTrace (generated):
- SP IP Function
- 024AF2C8 0FE3125E App_Code_da2s7oyo!BuggyMail.IsValidEmailAddress(System.String)+0x76
- 024AF2E8 0FE31192 App_Code_da2s7oyo!BuggyMail.SendEmail(System.String, System.String)+0x4a
- StackTraceString: <none>
- HResult: 80131500
- There are nested exceptions on this thread. Run with -nested for details
- ********************************
- Exception object: 02ea75f0
- Exception type: System.IO.DirectoryNotFoundException
- Message: Could not find a part of the path 'c:\idontexist\log.txt'.
- InnerException: <none>
- StackTrace (generated):
- SP IP Function
- 024AF044 792741F2 mscorlib_ni!System.IO.__Error.WinIOError(Int32, System.String)+0xc2
- 024AF0A0 792EB22B mscorlib_ni!System.IO.FileStream.Init(System.String, System.IO.FileMode, System.IO.FileAccess, Int32, Boolean, System.IO.FileShare, Int32, System.IO.FileOptions, SECURITY_ATTRIBUTES, System.String, Boolean)+0x48b
- 024AF198 792EA882 mscorlib_ni!System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare, Int32, System.IO.FileOptions)+0x42
- 024AF1C0 7927783F mscorlib_ni!System.IO.StreamWriter.CreateFile(System.String, Boolean)+0x3f
- 024AF1D4 792777DB mscorlib_ni!System.IO.StreamWriter..ctor(System.String, Boolean, System.Text.Encoding, Int32)+0x3b
- 024AF1F4 797EE19F mscorlib_ni!System.IO.StreamWriter..ctor(System.String)+0x1f
- 024AF204 0FE31325 App_Code_da2s7oyo!Utility.WriteToLog(System.String, System.String)+0x5d
- StackTraceString: <none>
- HResult: 80070003
- There are nested exceptions on this thread. Run with -nested for details
- ********************************
- Exception object: 02ea7de8
- Exception type: System.IO.DirectoryNotFoundException
- Message: Could not find a part of the path 'c:\idontexist\log.txt'.
- InnerException: <none>
- StackTrace (generated):
- SP IP Function
- 024AEF60 792741F2 mscorlib_ni!System.IO.__Error.WinIOError(Int32, System.String)+0xc2
- 024AEFBC 792EB22B mscorlib_ni!System.IO.FileStream.Init(System.String, System.IO.FileMode, System.IO.FileAccess, Int32, Boolean, System.IO.FileShare, Int32, System.IO.FileOptions, SECURITY_ATTRIBUTES, System.String, Boolean)+0x48b
- 024AF0B4 792EA882 mscorlib_ni!System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare, Int32, System.IO.FileOptions)+0x42
- 024AF0DC 7927783F mscorlib_ni!System.IO.StreamWriter.CreateFile(System.String, Boolean)+0x3f
- 024AF0F0 792777DB mscorlib_ni!System.IO.StreamWriter..ctor(System.String, Boolean, System.Text.Encoding, Int32)+0x3b
- 024AF110 797EE19F mscorlib_ni!System.IO.StreamWriter..ctor(System.String)+0x1f
- 024AF120 0FE31325 App_Code_da2s7oyo!Utility.WriteToLog(System.String, System.String)+0x5d
- StackTraceString: <none>
- HResult: 80070003
- There are nested exceptions on this thread. Run with -nested for details
当然你也可以打印出当前异常的内部异常,配上一个 -nest 参数即可。
- .foreach (ex {!dumpheap -type Exception -short}){.echo "********************************";!pe –nested ${ex} }