程序崩溃时自动记录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();

private:

       LPTOP_LEVEL_EXCEPTION_FILTER m_OriginalFilter;

       static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo);

};


namespace

{
       const bool bPlaceHolder = CrashDumper::_PlaceHolder();

}

#endif

 

实现文件:

crash_dumper_w32.cpp

 

#include <windows.h>

#include <tchar.h>

#include <dbghelp.h>

#include <string>

 

#include "crash_dumper_w32.h"

 

#ifdef UNICODE    

#     define tstring wstring     

#else       

#     define tstring string 

#endif

 

#pragma comment(lib, "dbghelp.lib")

 

CrashDumper dumper;

 

CrashDumper::CrashDumper()

{

       m_OriginalFilter = SetUnhandledExceptionFilter(ExceptionFilter);

}

 

CrashDumper::~CrashDumper()

{

       SetUnhandledExceptionFilter(m_OriginalFilter);

}

 

LONG WINAPI CrashDumper::ExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)

{

       bool bDumpOK = false;

       DWORD dwProcess = GetCurrentProcessId();

       HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcess);

       if (hProcess != INVALID_HANDLE_VALUE)

       {

              TCHAR szPath[MAX_PATH];

              if (GetModuleFileName(NULL, szPath, sizeof(szPath)))

              {

                     std::tstring strDumpFileName = szPath;

                     strDumpFileName += TEXT(".dmp");

                     HANDLE hFile = CreateFile(strDumpFileName.c_str(), FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, NULL, NULL);

                     if (hFile != INVALID_HANDLE_VALUE)

                     {

                            MINIDUMP_EXCEPTION_INFORMATION exception_information;

                            exception_information.ThreadId = GetCurrentThreadId();

                            exception_information.ExceptionPointers = ExceptionInfo;

                            exception_information.ClientPointers = TRUE;

                            if (MiniDumpWriteDump(hProcess, dwProcess, hFile, MiniDumpNormal, &exception_information, NULL, NULL))

                            {

                                   bDumpOK = true;

                            }

 

                            CloseHandle(hFile);

                     }

              }

 

              CloseHandle(hProcess);

       }

 

       if (bDumpOK)

              MessageBox(NULL, TEXT("本程序遇到未处理的异常,MiniDump文件已经生成在程序的运行目录。"), TEXT("提示"), MB_OK);

       else

              MessageBox(NULL, TEXT("本程序遇到未处理的异常,生成MiniDump文件失败。"), TEXT("提示"), MB_OK);

 

       return EXCEPTION_EXECUTE_HANDLER;

}
 

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)