zoukankan      html  css  js  c++  java
  • Dump定位程序崩溃闪退问题

    Dump定位程序崩溃闪退问题

    作用

    WinForm或其他程序崩溃闪退无法找到根本原因时,崩溃前使用此类为进程创建DUMP文件,之后可以使用WinDbg等工具进行分析。

    辅助类代码

    网上下载dbghelp.dllkernel32.dll两个dll添加到项目,属性选择始终复制。

    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());
            }
        }
    }
    

    问题定位

    使用VS打开文件的方式打开error.dmp,选择“混合调试”,程序自动定位到崩溃代码行(注意需要运行环境的.pdb文件与调试.pdb文件一样,即要求调试的代码和运行代码一模一样),然后查看堆栈信息。

  • 相关阅读:
    Attributes in C#
    asp.net C# 时间格式大全
    UVA 10518 How Many Calls?
    UVA 10303 How Many Trees?
    UVA 991 Safe Salutations
    UVA 10862 Connect the Cable Wires
    UVA 10417 Gift Exchanging
    UVA 10229 Modular Fibonacci
    UVA 10079 Pizza Cutting
    UVA 10334 Ray Through Glasses
  • 原文地址:https://www.cnblogs.com/Nine4Cool/p/13939424.html
Copyright © 2011-2022 走看看