使用C#为进程创建DUMP文件

作用

程序异常崩溃前使用此类为进程创建DUMP文件,之后可以使用WinDbg等工具进行分析。



辅助类代码

using System;

using System.Diagnostics;

using System.IO;

using System.Runtime.InteropServices;



namespace Infrastructure

{

    public static class MiniDump

    {

        // Taken almost verbatim from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/

        [Flags]

        public enum Option : uint

        {

            // From dbghelp.h:

            Normal = 0x00000000,

            WithDataSegs = 0x00000001,

            WithFullMemory = 0x00000002,

            WithHandleData = 0x00000004,

            FilterMemory = 0x00000008,

            ScanMemory = 0x00000010,

            WithUnloadedModules = 0x00000020,

            WithIndirectlyReferencedMemory = 0x00000040,

            FilterModulePaths = 0x00000080,

            WithProcessThreadData = 0x00000100,

            WithPrivateReadWriteMemory = 0x00000200,

            WithoutOptionalData = 0x00000400,

            WithFullMemoryInfo = 0x00000800,

            WithThreadInfo = 0x00001000,

            WithCodeSegs = 0x00002000,

            WithoutAuxiliaryState = 0x00004000,

            WithFullAuxiliaryState = 0x00008000,

            WithPrivateWriteCopyMemory = 0x00010000,

            IgnoreInaccessibleMemory = 0x00020000,

            ValidTypeFlags = 0x0003ffff,

        }



        enum ExceptionInfo

        {

            None,

            Present

        }



        //typedef struct _MINIDUMP_EXCEPTION_INFORMATION {

        //    DWORD ThreadId;

        //    PEXCEPTION_POINTERS ExceptionPointers;

        //    BOOL ClientPointers;

        //} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;

        [StructLayout(LayoutKind.Sequential, Pack = 4)]  // Pack=4 is important! So it works also for x64!

        struct MiniDumpExceptionInformation

        {

            public uint ThreadId;

            public IntPtr ExceptionPointers;

            [MarshalAs(UnmanagedType.Bool)]

            public bool ClientPointers;

        }



        //BOOL

        //WINAPI

        //MiniDumpWriteDump(

        //    __in HANDLE hProcess,

        //    __in DWORD ProcessId,

        //    __in HANDLE hFile,

        //    __in MINIDUMP_TYPE DumpType,

        //    __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,

        //    __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,

        //    __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam

        //    );

        // Overload requiring MiniDumpExceptionInformation

        [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]



        static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);



        // Overload supporting MiniDumpExceptionInformation == NULL

        [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]

        static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);



        [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]

        static extern uint GetCurrentThreadId();



        static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo)

        {

            Process currentProcess = Process.GetCurrentProcess();

            IntPtr currentProcessHandle = currentProcess.Handle;

            uint currentProcessId = (uint)currentProcess.Id;

            MiniDumpExceptionInformation exp;

            exp.ThreadId = GetCurrentThreadId();

            exp.ClientPointers = false;

            exp.ExceptionPointers = IntPtr.Zero;

            if (exceptionInfo == ExceptionInfo.Present)

            {

                exp.ExceptionPointers = Marshal.GetExceptionPointers();

            }

            return exp.ExceptionPointers == IntPtr.Zero ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) : MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero);

        }



        static bool Write(SafeHandle fileHandle, Option dumpType)

        {

            return Write(fileHandle, dumpType, ExceptionInfo.None);

        }



        public static Boolean TryDump(String dmpPath, Option dmpType=Option.Normal)

        {

            var path = Path.Combine(Environment.CurrentDirectory, dmpPath);

            var dir = Path.GetDirectoryName(path);

            if (dir != null && !Directory.Exists(dir))

            {

                Directory.CreateDirectory(dir);

            }

            using (var fs = new FileStream(path, FileMode.Create))

            {

                return Write(fs.SafeFileHandle, dmpType);

            }

        }

    }

}


提示

对于Windows Form程序,可以利用AppDomain的UnhandledException事件。以下示例:

namespace WindowsFormsApplication1

{

    static class Program

    {

        /// <summary>

        /// 应用程序的主入口点。

        /// </summary>

        [STAThread]

        static void Main()

        {

            AppDomain.CurrentDomain.UnhandledException +=new UnhandledExceptionEventHandler((obj,args)=> MiniDump.TryDump("error.dmp"));



            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new Form1());

        }

    }

}


你可能感兴趣的:(dump)