您的位置:首页 > 其它

CrashReport,BugReport的核心--创建dump文件

2016-04-20 14:45 417 查看
// minidmp.h
#pragma once

#include <windows h="">
#include <imagehlp h="">
#include <stdlib h="">
#include <strsafe h="">
#pragma comment(lib, "dbghelp.lib")

inline BOOL IsDataSectionNeeded(const WCHAR *pModuleName)
{
if(pModuleName == 0)
{
return FALSE;
}

WCHAR szFileName[_MAX_FNAME] = L"";
_wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
if(wcsicmp(szFileName, L"ntdll") == 0)
return TRUE;

return FALSE;
}

inline BOOL CALLBACK MiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput)
{
if(pInput == 0 || pOutput == 0)
return FALSE;

switch(pInput->CallbackType)
{
case ModuleCallback:
if(pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
if(!IsDataSectionNeeded(pInput->Module.FullPath))
pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);

break;

case IncludeModuleCallback:
case IncludeThreadCallback:
case ThreadCallback:
case ThreadExCallback:
return TRUE;

default:
break;
}

return FALSE;
}

//创建Dump文件
inline void CreateMiniDump(EXCEPTION_POINTERS *pep, LPCWSTR strFileName)
{
HANDLE hFile = CreateFileW(strFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
{
MINIDUMP_EXCEPTION_INFORMATION mdei;
mdei.ThreadId           = GetCurrentThreadId();
mdei.ExceptionPointers  = pep;
mdei.ClientPointers     = FALSE;
MINIDUMP_CALLBACK_INFORMATION mci;
mci.CallbackRoutine     = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;
mci.CallbackParam       = 0;
MINIDUMP_TYPE mdt       = (MINIDUMP_TYPE)0x0000ffff;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, NULL, &mci);
CloseHandle(hFile);
}
}

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
{
return NULL;
}

BOOL PreventSetUnhandledExceptionFilter()
{
HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
if (hKernel32 ==   NULL)
return FALSE;

void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
if(pOrgEntry == NULL)
return FALSE;

unsigned char newJump[ 100 ];
DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far

void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
DWORD dwNewEntryAddr = (DWORD) pNewFunc;
DWORD dwRelativeAddr = dwNewEntryAddr -  dwOrgEntryAddr;

newJump[ 0 ] = 0xE9;  // JMP absolute
memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc));
SIZE_T bytesWritten;
BOOL bRet = WriteProcessMemory(GetCurrentProcess(),    pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
return bRet;
}

LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS *pException)
{
WCHAR szPath[MAX_PATH];
WCHAR szFileName[MAX_PATH];
WCHAR *szAppName = L"DumpFile";
HANDLE hDumpFile;
SYSTEMTIME stLocalTime;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
GetLocalTime( &stLocalTime );
//GetTempPath( dwBufferSize, szPath );
GetModuleFileNameW(NULL, szPath, MAX_PATH);
wchar_t *pstr = wcsrchr(szPath, '\\');
memset(pstr + 1, 0, 2);

StringCchPrintfW( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
CreateDirectoryW( szFileName, NULL );
StringCchPrintfW( szFileName, MAX_PATH, L"%s%s\\%04d%02d%02d-%02d%02d%02d.dmp", szPath, szAppName,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);

CreateMiniDump(pException, szFileName);
// TODO: 这里可以将dump文件通过邮件发送给开发者,也可以通过http发送给服务端,服务端管理dump文件
FatalAppExit(-1,  _T("*** Unhandled Exception! ***"));

return EXCEPTION_CONTINUE_SEARCH;
}

//运行异常处理
void RunCrashHandler()
{
SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);
PreventSetUnhandledExceptionFilter();
}
// Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "minidmp.h"

void CrashTest()
{
strcpy(NULL,"adfadfg");
}

int _tmain(int argc, _TCHAR* argv[])
{
//设置异常处理回调函数
RunCrashHandler();

CrashTest();

getchar();
return 0;
}

核心就是这样了,注意点:程序发布时记得带上dbghelp.dll,这个是系统dll,开发机上肯定都会有。剩下的就是把dump文件上传到服务器或者直接使用邮件发到指定邮箱了。

有了dump文件,结合发布版本的pdb文件以及源代码就能很快定位到崩溃点了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: