C#使用MiniDump捕获异常

c/c++语言里MiniDump是一个重要的调试手段,他们没有C#/java这样语言有很多异常输出信息(

JVM异常导出bug日志功能,通常在jdk目录,文件格式hs_err_%pid%.log,pid是进程id)。

我们通常在项目中都会把可预见性进行异常处理。常见的处理方法如下

try{

   ...

catch(Exception ex)
{
   HandleExeption(ex);
}

项目部署到客户机中运行在程序员无法评估的情况下,如(堆栈溢出、访问冲突)则无法处理

或者很难重现这种异常,这给程序调试带来一定程度上的障碍,而这个时候内存及当前机器环境的快

照信息对程序排错则至关重要。幸好我们.NET提供了应用程序域未捕获异常(不是所有异常)事件处理

接口AppDomain.UnhandledException先贴出Minidump封装类:

public sealed class MiniDump
    {
        [Flags]
        public enum DumpType : uint
        {
            // From dbghelp.h:
            MiniDumpNormal = 0x00000000,
            MiniDumpWithDataSegs = 0x00000001,
            MiniDumpWithFullMemory = 0x00000002,
            MiniDumpWithHandleData = 0x00000004,
            MiniDumpFilterMemory = 0x00000008,
            MiniDumpScanMemory = 0x00000010,
            MiniDumpWithUnloadedModules = 0x00000020,
            MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
            MiniDumpFilterModulePaths = 0x00000080,
            MiniDumpWithProcessThreadData = 0x00000100,
            MiniDumpWithPrivateReadWriteMemory = 0x00000200,
            MiniDumpWithoutOptionalData = 0x00000400,
            MiniDumpWithFullMemoryInfo = 0x00000800,
            MiniDumpWithThreadInfo = 0x00001000,
            MiniDumpWithCodeSegs = 0x00002000,
            MiniDumpWithoutAuxiliaryState = 0x00004000,
            MiniDumpWithFullAuxiliaryState = 0x00008000,
            MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
            MiniDumpIgnoreInaccessibleMemory = 0x00020000,
            MiniDumpValidTypeFlags = 0x0003ffff,
        };

        //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 ExceptioonPointers;
            [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
        //    );
        [DllImport("dbghelp.dll",
          EntryPoint = "MiniDumpWriteDump",
          CallingConvention = CallingConvention.StdCall,
          CharSet = CharSet.Unicode,
          ExactSpelling = true, SetLastError = true)]
        static extern bool MiniDumpWriteDump(
          IntPtr hProcess,
          uint processId,
          IntPtr hFile,
          uint dumpType,
          ref MiniDumpExceptionInformation expParam,
          IntPtr userStreamParam,
          IntPtr callbackParam);

        [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
        static extern uint GetCurrentThreadId();

        [DllImport("kernel32.dll", EntryPoint = "GetCurrentProcess", ExactSpelling = true)]
        static extern IntPtr GetCurrentProcess();

        [DllImport("kernel32.dll", EntryPoint = "GetCurrentProcessId", ExactSpelling = true)]
        static extern uint GetCurrentProcessId();

        public static bool Write(string fileName)
        {
            return Write(fileName, DumpType.MiniDumpWithFullMemory);
        }
        public static bool Write(string fileName, DumpType dumpType)
        {
            using (var fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
            {
                MiniDumpExceptionInformation exp;
                exp.ThreadId = GetCurrentThreadId();
                exp.ClientPointers = false;
                exp.ExceptioonPointers = System.Runtime.InteropServices.Marshal.GetExceptionPointers();
                bool bRet = MiniDumpWriteDump(
                  GetCurrentProcess(),
                  GetCurrentProcessId(),
                  fs.SafeFileHandle.DangerousGetHandle(),
                  (uint)dumpType,
                  ref exp,
                  IntPtr.Zero,
                  IntPtr.Zero);
                return bRet;
            }
        }

以下以Winform演示这个事件的使用方法

先拖一个界面如下

static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            Application.ThreadException += Application_ThreadException;

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }

        private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            string dumpFile = System.IO.Path.Combine(System.Environment.CurrentDirectory, "dump.dmp");
            MiniDump.Write(dumpFile);
        }

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            string dumpFile = System.IO.Path.Combine(System.Environment.CurrentDirectory, "dump.dmp");
            MiniDump.Write(dumpFile);
        }

    }

两个按钮事件代码分别如下:

private void button1_Click(object sender, EventArgs e)
        {
            new Thread(() => { throw new Exception("Other thread"); }).Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {

            string a = null;
            a.PadLeft(10);
        }

随便点击一个按钮都能触发异常处理,生成如下dump.dmp文件

拖到visual studio里面打开如下

最近比较忙,时间紧张,文章写得比较粗糙,大家应该能明白什么意思了,有疑问欢迎留言。

参考:

AppDomain.CurrentDomain.UnhandledException not firing without debugging

Writing MiniDumps in C#

application level global exception handler didn‘t get hit

How to create minidump of a .NET process when a certain first chance exception occurs

Should use both AppDomain.UnhandledException and Application.DispatcherUnhandledException?

The simplest way to generate minidump for mixed managed & unmanaged stack?

CLRDUMP

How to Use the Debug Diagnostic Tool v1.1 (DebugDiag) to Debug User Mode Processes

Bugslayer SUPERASSERT Goes .NET

Adplus 抓取Crash Dump

原文地址:https://www.cnblogs.com/passedbylove/p/9097032.html

时间: 2024-10-10 07:08:55

C#使用MiniDump捕获异常的相关文章

未捕获异常,现实程序崩溃闪退

碰到程序崩溃时,闪退效果,不会提示"xxx程序异常,退出程序".这样的效果就要使用到未捕获异常来实现,这里记录了我的一个写法.其实原理很简单,设置程序的未捕获异常监听,实现监听的一个方法,在该方法中现实直接没有提示的退出程序. 捕获异常工具类 package com.tdh.http; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.Thread.UncaughtExceptionHan

【转】程序崩溃时自动记录minidump的c++类

原帖:程序崩溃时自动记录minidump的c++类 封装了一个C++类,当程序意外崩溃的时候可以生成dump文件,以便确定错误原因. 头文件: //crash_dumper_w32.h #ifndef _CRASH_DUMPER_H_ #define _CRASH_DUMPER_H_ #include <windows.h> class CrashDumper { public: CrashDumper(); ~CrashDumper(); static bool _PlaceHolder()

JNI捕获异常

jnihelp.h头文件根据需求自行添加,也可以直接删除 #define LOG_TAG "JNIHelp"#include "JNIHelp.h"#include "android/log.h"#include <string.h>#include <assert.h>#include <stdio.h>#include <stdlib.h> static void getExceptionSum

node 进阶 | 通过node中如何捕获异常阐述express的特点

node如何捕获异常 node基于js的单线程,有了非阻塞异步回调的概念,但是在处理多个并发连接时,并发环境要求高,最重要的是单线程,单核CPU,一个进程crash则web服务都crash,但是为什么node还这么火?甚至有了Node工程师这个岗,肯定就是node有自己crash之前与之后的解决方法,比如捕获异常 问:nodejs如何捕获异常?答:回调函数中有err形参,console.log出来,这是我之前回答别人问题的答案,但是自从我这几天看了如何捕获异常,才知道捕获异常的精髓就是不要让服务

C#高级编程八十一天----捕获异常

捕获异常 前面主要说了关于异常的一些基础和理论知识,没有进入到正真的异常案例,这一讲通过几个案例来描述一下异常的捕获和处理. 案例代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 异常处理 { class Program { int result; Program() { result =

捕获异常

在JAVA语言中,我们通常在一个方法中使用try和catch关键字来捕获异常 使用try/catch关键字的代码块可能产生异常的代码包围起来,其中的代码也被称为被保护的代码 使用try和catch的语法形式如下所示: try{ //被保护的代码 }catch(异常的名称 e1){ //捕获块 } catch语句包含我们想要捕获的异常的类型声明,如果在被保护的代码中发生异常,try块后面的catch块就会尝试对这个异常进行检查 如果发生的异常类型是在catch语句中所罗列出来的,那么异常对象就像方

异常处理与MiniDump详解(4) MiniDump

http://blog.csdn.net/vagrxie/article/details/4398721 异常处理与MiniDump详解(4) MiniDump 分类:             [Windows]              2009-07-31 23:18     23631人阅读     评论(12)     收藏     举报 exceptionpointersmicrosoftfunwindowsnull 目录(?)[+] 一   综述 二   基本应用 怎么感知到程序的崩

Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题

最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚. 例:     类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) : if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.save(capabilityQuota); }

捕获异常、存sd卡、封装请求头体、加密map值、网络工具类、生成Json、Https协议、传log日志到服务器、app崩溃友好重启

点击打开链接,免积分下载 在集成了统计SDK(友盟统计,百度统计等)之后,有一个非常有利于测试的功能:错误分析!此功能能够将程序在运行中碰到的崩溃(runtimeException)问题反馈到服务器,帮助开发者改善产品,多适配机器.然而在公司android开发中不集成这些SDK,那应该怎么实现这样的功能呢?下面让我们来看下如何使用UncaughtExceptionHandler来捕获异常. 在Android开发中,常常会出现uncheched Exception 导致程序的crash,为了提供良