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

封装了一个C++类,当程序意外崩溃的时候可以生成dump文件,以便确定错误原因。

头文件:

 1 //crash_dumper_w32.h
 2 
 3 #ifndef _CRASH_DUMPER_H_
 4 
 5 #define _CRASH_DUMPER_H_
 6 
 7 
 8 #include <windows.h>
 9 
10 class CrashDumper
11 
12 {
13 
14 public:
15 
16        CrashDumper();
17 
18        ~CrashDumper();
19 
20        static bool _PlaceHolder();
21 
22 private:
23 
24        LPTOP_LEVEL_EXCEPTION_FILTER m_OriginalFilter;
25 
26        static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo);
27 
28 };
29 
30 
31 namespace
32 
33 {
34        const bool bPlaceHolder = CrashDumper::_PlaceHolder();
35 
36 }
37 
38 #endif

实现文件:

 

  1 crash_dumper_w32.cpp
  2 
  3  
  4 
  5 #include <windows.h>
  6 
  7 #include <tchar.h>
  8 
  9 #include <dbghelp.h>
 10 
 11 #include <string>
 12 
 13  
 14 
 15 #include "crash_dumper_w32.h"
 16 
 17  
 18 
 19 #ifdef UNICODE    
 20 
 21 #     define tstring wstring     
 22 
 23 #else       
 24 
 25 #     define tstring string 
 26 
 27 #endif
 28 
 29  
 30 
 31 #pragma comment(lib, "dbghelp.lib")
 32 
 33  
 34 
 35 CrashDumper dumper;
 36 
 37  
 38 
 39 CrashDumper::CrashDumper()
 40 
 41 {
 42 
 43        m_OriginalFilter = SetUnhandledExceptionFilter(ExceptionFilter);
 44 
 45 }
 46 
 47  
 48 
 49 CrashDumper::~CrashDumper()
 50 
 51 {
 52 
 53        SetUnhandledExceptionFilter(m_OriginalFilter);
 54 
 55 }
 56 
 57  
 58 
 59 LONG WINAPI CrashDumper::ExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
 60 
 61 {
 62 
 63        bool bDumpOK = false;
 64 
 65        DWORD dwProcess = GetCurrentProcessId();
 66 
 67        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);
 68 
 69        if (hProcess != INVALID_HANDLE_VALUE)
 70 
 71        {
 72 
 73               TCHAR szPath[MAX_PATH];
 74 
 75               if (GetModuleFileName(NULL, szPath, sizeof(szPath)))
 76 
 77               {
 78 
 79                      std::tstring strDumpFileName = szPath;
 80 
 81                      strDumpFileName += TEXT(".dmp");
 82 
 83                      HANDLE hFile = CreateFile(strDumpFileName.c_str(), FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, NULL, NULL);
 84 
 85                      if (hFile != INVALID_HANDLE_VALUE)
 86 
 87                      {
 88 
 89                             MINIDUMP_EXCEPTION_INFORMATION exception_information;
 90 
 91                             exception_information.ThreadId = GetCurrentThreadId();
 92 
 93                             exception_information.ExceptionPointers = ExceptionInfo;
 94 
 95                             exception_information.ClientPointers = TRUE;
 96 
 97                             if (MiniDumpWriteDump(hProcess, dwProcess, hFile, MiniDumpNormal, &exception_information, NULL, NULL))
 98 
 99                             {
100 
101                                    bDumpOK = true;
102 
103                             }
104 
105  
106 
107                             CloseHandle(hFile);
108 
109                      }
110 
111               }
112 
113  
114 
115               CloseHandle(hProcess);
116 
117        }
118 
119  
120 
121        if (bDumpOK)
122 
123               MessageBox(NULL, TEXT("本程序遇到未处理的异常,MiniDump文件已经生成在程序的运行目录。"), TEXT("提示"), MB_OK);
124 
125        else
126 
127               MessageBox(NULL, TEXT("本程序遇到未处理的异常,生成MiniDump文件失败。"), TEXT("提示"), MB_OK);
128 
129  
130 
131        return EXCEPTION_EXECUTE_HANDLER;
132 
133 }
134  
135 
136 bool CrashDumper::_PlaceHolder() {return true;}

代码很简单,唯一需要提一下的是下面的一句代码,这个技巧是为了解决当crash_dumper_w32.cpp文件被编译成单独的静态库在程序中使用不起作用的问题。

 

namespace

{

       const bool bPlaceHolder = CrashDumper::_PlaceHolder();

}

 

之所以在静态库中.cpp中的代码不起作用,是因为没有代码去调用crash_dumper_w32.cpp的代码,链接的时候就被编译器给丢掉了。上面的语句在匿名空间中定义了一个变量,这样,每一个包含它的.cpp文件就“被迫”创建了一个不可访问的bPlaceHolder变量,而该变量又必须使用CrashDumper::_PlaceHolder()函数来初始化。crash_dumper_w32.cpp文件的代码就被强制链接进来了。

 

此外,如果是服务类型的程序,还可以在异常处理函数中增加自动启动新实例的功能,以保证服务不间断。

你可能感兴趣的:(dump)