Windows下收集崩溃信息C++代码
// MiniDump.h : include file for standard system include files,
// or project specific include files
//
#pragma once
#include <tchar.h>
#include <stdio.h>
#include <winsock2.h>
#include <dbghelp.h>
class MiniDump {
typedef BOOL(WINAPI* PFN_MiniDumpWriteDump)(HANDLE hProcess,
DWORD dwPid,
HANDLE hFile,
MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
CRITICAL_SECTION m_CriticalSection = { 0 };
public:
MiniDump() {
// The SetUnhandledExceptionFilter function enables an application to
// supersede the top-level exception handler of each thread and process.
// After calling this function, if an exception occurs in a process
// that is not being debugged, and the exception makes it to the
// unhandled exception filter, that filter will call the exception
// filter function specified by the lpTopLevelExceptionFilter parameter.
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
// Since DBGHELP.dll is not inherently thread-safe, making calls into it
// from more than one thread simultaneously may yield undefined behavior.
// This means that if your application has multiple threads, or is
// called by multiple threads in a non-synchronized manner, you need to
// make sure that all calls into DBGHELP.dll are isolated via a global
// critical section.
InitializeCriticalSection(&m_CriticalSection);
}
virtual ~MiniDump() {
DeleteCriticalSection(&m_CriticalSection);
}
private:
static LONG WINAPI UnhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
MiniDump * thiz = MiniDump::Init();
if (thiz == NULL)
{
return EXCEPTION_CONTINUE_SEARCH;
}
return thiz->WriteMiniDump(pExceptionInfo);
}
LONG WriteMiniDump(PEXCEPTION_POINTERS pExceptionInfo) {
LONG lRetValue = EXCEPTION_CONTINUE_SEARCH;
// You have to find the right dbghelp.dll.
// Look next to the EXE first since the one in System32 might be old (Win2k)
HANDLE hMiniDumpFile = NULL;
HMODULE hModuleDbgHelp = NULL;
TCHAR szModuleFilePath[MAX_PATH] = { 0 };
TCHAR szMiniDumpFilePath[MAX_PATH] = { 0 };
PFN_MiniDumpWriteDump MiniDumpWriteDump = NULL;
MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo = { 0 };
GetModuleFileName(NULL, szModuleFilePath, _MAX_PATH);
// If we haven't found it yet - try one more time.
hModuleDbgHelp = LoadLibrary(TEXT("DBGHELP"));
if (hModuleDbgHelp != NULL)
{
// Get the address of the MiniDumpWriteDump function, which writes
// user-mode mini-dump information to a specified file.
MiniDumpWriteDump = (PFN_MiniDumpWriteDump)GetProcAddress(hModuleDbgHelp, "MiniDumpWriteDump");
}
if (MiniDumpWriteDump != NULL)
{
ExceptionInfo.ThreadId = GetCurrentThreadId();
ExceptionInfo.ExceptionPointers = pExceptionInfo;
ExceptionInfo.ClientPointers = NULL;
wsprintf(szMiniDumpFilePath, TEXT("%s.dmp"), szModuleFilePath);
// Create the mini-dump file...
hMiniDumpFile = CreateFile(szMiniDumpFilePath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hMiniDumpFile != INVALID_HANDLE_VALUE)
{
// DBGHELP.dll is not thread-safe, so we need to restrict access...
EnterCriticalSection(&m_CriticalSection);
// Write out the mini-dump data to the file...
if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hMiniDumpFile, MiniDumpNormal, &ExceptionInfo, NULL, NULL) == TRUE)
{
lRetValue = EXCEPTION_EXECUTE_HANDLER;
}
LeaveCriticalSection(&m_CriticalSection);
CloseHandle(hMiniDumpFile);
hMiniDumpFile = NULL;
}
}
return lRetValue;
}
public:
static MiniDump* Init() {
static MiniDump MiniDumpInstance;
return &MiniDumpInstance;
}
};