事后调试之MiniDump生成与调试_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 事后调试之MiniDump生成与调试

事后调试之MiniDump生成与调试

 2013/10/29 22:58:02  山海  博客园  我要评论(0)
  • 摘要:程序发布后,针对在用户使用过程中出现的一些问题进行调试,这个过程可以称为是事后调试。在程序Crash时转储MiniDump文件供软件开发工程师分析是一种比较常用的方法。1.MiniDumpWriteDumpMiniDumpWriteDump是windowsDbgHelp.dll提供的一个转储进程MiniDump的API,可以将其导入到C#程序中。1usingSystem;2usingSystem.Diagnostics;3usingSystem.IO;4usingSystem.Runtime
  • 标签:

程序发布后,针对在用户使用过程中出现的一些问题进行调试,这个过程可以称为是事后调试。在程序Crash时转储MiniDump文件供软件开发工程师分析是一种比较常用的方法。

 

1. MiniDumpWriteDump

MiniDumpWriteDump是windows DbgHelp.dll提供的一个转储进程MiniDump的API,可以将其导入到C#程序中。

class="code_img_closed" src="/Upload/Images/2013102922/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('5df8cd5f-dace-4e8d-8493-e7d5d81baa5d',event)" src="/Upload/Images/2013102922/2B1B950FA3DF188F.gif" alt="" />
 1     using System;
 2     using System.Diagnostics;
 3     using System.IO;
 4     using System.Runtime.InteropServices;
 5     using System.Threading;
 6 
 7     public class MiniDumpUtil
 8     {
 9         [DllImport("kernel32.dll")]
10         private static extern int GetCurrentThreadId();
11 
12         [DllImport("DbgHelp.dll")]
13         private static extern bool MiniDumpWriteDump(IntPtr hProcess, int processId, IntPtr fileHandle, MiniDumpType dumpType,ref MiniDumpExceptionInfo excepInfo, IntPtr userInfo, IntPtr extInfo);
14 
15         [DllImport("DbgHelp.dll")]
16         private static extern bool MiniDumpWriteDump(IntPtr hProcess, int processId, IntPtr fileHandle, MiniDumpType dumpType, IntPtr excepParam, IntPtr userInfo, IntPtr extInfo);
17 
18         public static bool TryWriteMiniDump(string dmpFileName, MiniDumpType dmpType)
19         {
20             using (FileStream stream = new FileStream(dmpFileName, FileMode.OpenOrCreate))
21             {
22                 Process process = Process.GetCurrentProcess();
23                 MiniDumpExceptionInfo exceptionInfo = new MiniDumpExceptionInfo();
24                 exceptionInfo.ThreadId = GetCurrentThreadId();
25                 exceptionInfo.ExceptionPointers = Marshal.GetExceptionPointers();
26                 exceptionInfo.ClientPointers = true;
27                 if (exceptionInfo.ExceptionPointers == IntPtr.Zero)
28                 {
29                     return MiniDumpWriteDump(process.Handle, process.Id, stream.SafeFileHandle.DangerousGetHandle(), dmpType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
30                 }
31                 else
32                 {
33                     return MiniDumpWriteDump(process.Handle, process.Id, stream.SafeFileHandle.DangerousGetHandle(), dmpType, ref exceptionInfo, IntPtr.Zero, IntPtr.Zero);
34                 }
35             }
36         }
37     }
38 
39     public enum MiniDumpType
40     {
41         MiniDumpNormal = 0x00000000,
42         MiniDumpWithDataSegs = 0x00000001,
43         MiniDumpWithFullMemory = 0x00000002,
44         MiniDumpWithHandleData = 0x00000004,
45         MiniDumpFilterMemory = 0x00000008,
46         MiniDumpScanMemory = 0x00000010,
47         MiniDumpWithUnloadedModules = 0x00000020,
48         MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
49         MiniDumpFilterModulePaths = 0x00000080,
50         MiniDumpWithProcessThreadData = 0x00000100,
51         MiniDumpWithPrivateReadWriteMemory = 0x00000200,
52         MiniDumpWithoutOptionalData = 0x00000400,
53         MiniDumpWithFullMemoryInfo = 0x00000800,
54         MiniDumpWithThreadInfo = 0x00001000,
55         MiniDumpWithCodeSegs = 0x00002000,
56         MiniDumpWithoutAuxiliaryState = 0x00004000,
57         MiniDumpWithFullAuxiliaryState = 0x00008000,
58         MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
59         MiniDumpIgnoreInaccessibleMemory = 0x00020000,
60         MiniDumpWithTokenInformation = 0x00040000,
61         MiniDumpWithModuleHeaders = 0x00080000,
62         MiniDumpFilterTriage = 0x00100000,
63         MiniDumpValidTypeFlags = 0x001fffff
64     }
65 
66     public struct MiniDumpExceptionInfo
67     {
68         public int ThreadId;
69         public IntPtr ExceptionPointers;
70         public bool ClientPointers;
71     }
MiniDumpUtil

 这里要注意的一点是当前线程的ID,不能用当前线程的托管线程ID(即Thread.CurrentThread.ManagedThreadId),而是用当前线程的操作系统ID(即OSID),否则用windbg加载dump文件时可能会出现一些错误信息:

ERROR: Unable to find system thread 1
ERROR: The thread being debugged has either exited or cannot be accessed
ERROR: Many commands will not work properly

当然,这似乎对调试影响并不是很大,切换线程很容易通过windbg命令完成。

可以简单地在未处理异常中转储进程的MiniDump

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
 6 
 7             TestMethod(-1);
 8         }
 9 
10         static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
11         {
12             MiniDumpUtil.TryWriteMiniDump("E:\\dump\\test.dmp", MiniDumpType.MiniDumpWithFullMemory);
13         }
14 
15         static void TestMethod(int num)
16         {
17             if (num < 0)
18             {
19                 throw new ArgumentException("The argument 'num' is less than zero!");
20             }
21         }
22     }
View Code

运行程序后,会生成test.dmp文件,用windbg加载该dump文件,设置pdb路径,可以分析异常信息。以下是采用windbg分析输出的一些信息:

Loading Dump File [E:\dump\test.dmp]

User Mini Dump File with Full Memory: Only application data is available

Symbol search path is: srv*

Executable search path is:

Windows 7 Version 7600 MP (4 procs) Free x86 compatible

Product: WinNt, suite: SingleUserTS

Machine Name:

Debug session time: Tue Oct 29 21:42:14.000 2013 (UTC + 8:00)

System Uptime: 0 days 2:42:59.907

Process Uptime: not available

...............................

This dump file has an exception of interest stored in it.

The stored exception information can be accessed via .ecxr.

(168.1474): CLR exception - code e0434352 (first/second chance not available)

eax=fffffffd ebx=038b0d78 ecx=0013d7f8 edx=77886194 esi=038b0d38 edi=0013d898

eip=77886194 esp=0013d558 ebp=0013d568 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!KiFastSystemCallRet:

77886194 c3              ret

0:000> .sympath+ E:\dump

Symbol search path is: srv*;E:\dump

Expanded Symbol search path is: cache*;SRV*http://msdl.microsoft.com/download/symbols;e:\dump

0:000> .loadby sos clr

0:000> !pe

Exception object: 017eb58c

Exception type:   System.ArgumentException

Message:          The argument 'num' is less than zero!

InnerException:   <none>

StackTrace (generated):

    SP       IP       Function

    0013EC98 002B00E6 DumpUtilDemo!DumpUtilDemo.Program.Main(System.String[])+0x76

StackTraceString: <none>

HResult: 80070057

 

 

  • 相关文章
发表评论
用户名: 匿名