#ifndef CRASHHOOK_H
#define CRASHHOOK_H
#include <string>
class ApplicationCrashEvents
{
public:
virtual void onCrash(const std::string &dumpPath) = 0;
};
class CrashHook
{
public:
explicit CrashHook(ApplicationCrashEvents *notifier = NULL);
virtual ~CrashHook();
};
#endif // CRASHHOOK_H
#include "crashhook.h"
#include <Windows.h>
#include <string.h>
#include <time.h>
#include <DbgHelp.h>
#include <sstream>
#pragma comment(lib, "DbgHelp.lib")
static ApplicationCrashEvents *s_notifier = 0;
static const int s_pathLen = 1024;
LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS *pExceptionInfo);
CrashHook::CrashHook(ApplicationCrashEvents *notifier)
{
s_notifier = notifier;
::SetUnhandledExceptionFilter(topLevelExceptionFilter);
}
CrashHook::~CrashHook()
{
}
LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS *pExceptionInfo)
{
LONG retValue = EXCEPTION_CONTINUE_SEARCH;
std::string buffer;
buffer.resize(s_pathLen + 1, '\0');
::GetModuleFileNameA(NULL, &buffer[0], s_pathLen);
std::string dir = buffer.substr(0, buffer.find_last_of("\\"));
char path[s_pathLen + 1] = {0};
time_t tim = time(NULL);
tm *t = localtime(&tim);
sprintf(path, "%s\\crash%d%02d%02d%02d%02d%02d.dmp", dir.c_str(),
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
HANDLE hFile = ::CreateFileA(path,
GENERIC_WRITE,
FILE_SHARE_WRITE,
0,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
if (hFile == INVALID_HANDLE_VALUE) {
std::wstringstream wss;
wss << L"create dump error, last error:" << GetLastError();
MessageBox(NULL, wss.str().c_str(), L"warning", MB_OK);
return retValue;
}
_MINIDUMP_EXCEPTION_INFORMATION exInfo;
exInfo.ThreadId = ::GetCurrentThreadId();
exInfo.ExceptionPointers = pExceptionInfo;
exInfo.ClientPointers = 0;
BOOL result = MiniDumpWriteDump(GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
&exInfo,
0,
0);
if (result == 0) {
std::wstringstream wss;
wss << L"write dump error, last error:" << GetLastError();
MessageBox(NULL, wss.str().c_str(), L"warning", MB_OK);
return retValue;
}
if (s_notifier) {
s_notifier->onCrash(path);
}
retValue = EXCEPTION_EXECUTE_HANDLER;
if (hFile != 0) {
CloseHandle(hFile);
}
return retValue;
}