借助MiniDumpWriteDump函数把崩溃进程的调用堆栈、CPU寄存器等信息写入本地文件。然后我们可以调用我们的BugReport.exe程序,让他发送Dump文件给服务器,然后重启客户端程序。
LONG __stdcall MyExceptionFun( LPEXCEPTION_POINTERS lpExcept)
{
wchar_t szMsg[1024]={0};
wsprintf(szMsg, L"Error address:0x%x, error code:%u\n CPU register:eax=0x%x, ebx=0x%x, ecx=0x%x, edx=0x%x", \
lpExcept->ExceptionRecord->ExceptionAddress, lpExcept->ExceptionRecord->ExceptionCode,\
lpExcept->ContextRecord->Eax, lpExcept->ContextRecord->Ebx, lpExcept->ContextRecord->Ecx, lpExcept->ContextRecord->Edx);
//MessageBox(NULL, szMsg, L"异常详细信息:", MB_OK|MB_ICONERROR);
SL_LOG(szMsg);
HANDLE hProcess=GetCurrentProcess();
DWORD dwProcessID=GetProcessId(hProcess);
HANDLE hFile=CreateFile(L"c:\\exception.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ( INVALID_HANDLE_VALUE!=hFile && GetLastError()!=ERROR_ALREADY_EXISTS )
{
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId=GetCurrentThreadId();
mei.ExceptionPointers=lpExcept;
mei.ClientPointers=FALSE;
MiniDumpWriteDump(hProcess, dwProcessID, hFile, MiniDumpWithProcessThreadData, &mei, NULL, NULL);
CloseHandle(hFile);
}
return EXCEPTION_EXECUTE_HANDLER;
}
切记,返回EXCEPTION_EXECUTE_HANDLER告诉系统这个崩溃我们已经处理了,系统就不会弹出那个可恶的崩溃对话框出来。
最重要的是在Main函数入口调用API:
::SetUnhandledExceptionFilter(MyExceptionFun);
MSDN说明:
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.