如何把 .NET 進程中的所有托管異常找出來?
大家應該知道 .NET異常 本質(zhì)上就是一個 Object 對象,也就是說只要你執(zhí)行了 new XXException() 語句,那么它就會分配到 GC Heap 上。
這也就意味著,如果你有一個進程的dump文件,那你就可以從dump中導出程序最近都拋了什么異常,換句話說只要這些異常沒有被 GC 回收,你都可以給它找出來。
實現(xiàn)起來很簡單,只要在 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
那現(xiàn)在問題來了,我想看所有異常的詳細信息怎么辦呢?人肉一個一個的用 !pe 命令去執(zhí)行,那將會多惡心。。。所以友好的方式就是寫腳本去提速,這里我使用 .foreach 命令。
- .foreach (ex {!dumpheap -type Exception -short}){.echo "********************************";!pe ${ex} }
上面我用了一個 -short 參數(shù),目的就是只輸出 address 地址方便腳本遍歷,然后將迭代項送入 !pe ,輸出結(jié)果如下:
- 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
當然你也可以打印出當前異常的內(nèi)部異常,配上一個 -nest 參數(shù)即可。
- .foreach (ex {!dumpheap -type Exception -short}){.echo "********************************";!pe –nested ${ex} }