[Windows编程] 如何捕捉程序异常/crash 并生成 dump 文件

前面介绍如如何用WinDBG 生成crash dump 《WinDBG 技巧:如何生成Dump 文件(.dump 命令) 》,但是用户机器上通常不安装WinDBG, 而且多数用户也不知道怎么使用WinDBG。 所以最好是自己程序里面能够捕捉exception/crash,并且生成crash dump,然后通过网络传回到自己服务器。
捕捉exception 可以用API 函数 SetUnhandledExceptionFilter 。生成crash dump 可以用DbgHelp.dll 里面的MiniDumpWriteDump 函数。
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter( __in LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter );
BOOL WINAPI MiniDumpWriteDump( __in HANDLE hProcess, __in DWORD ProcessId, __in HANDLE hFile, __in MINIDUMP_TYPE DumpType, __in PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, __in PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, __in PMINIDUMP_CALLBACK_INFORMATION CallbackParam );
代码示例:
view plaincopy to clipboardprint?
#include <dbghelp.h>  
#include <shellapi.h>  
#include <shlobj.h>  
 
 
// 自定义的exectpion filter  
LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pExceptionPointers)  
{  
 
    SetErrorMode( SEM_NOGPFAULTERRORBOX );  
 
    //收集信息  
     CStringW strBuild;  
    strBuild.Format(L"Build: %s %s", __DATE__, __TIME__);  
    CStringW strError;  
    HMODULE hModule;  
    WCHAR szModuleName[MAX_PATH] = L"";  
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, &hModule);  
    GetModuleFileName(hModule, szModuleName, ARRAYSIZE(szModuleName));  
    strError.AppenedFormat(L"%s %d , %d ,%d.", szModuleName,pExceptionPointers->ExceptionRecord->ExceptionCode, pExceptionPointers->ExceptionRecord->ExceptionFlags, pExceptionPointers->ExceptionRecord->ExceptionAddress);  
 
    //生成 mini crash dump  
    BOOL bMiniDumpSuccessful;  
    WCHAR szPath[MAX_PATH];   
    WCHAR szFileName[MAX_PATH];   
    WCHAR* szAppName = L"AppName";  
    WCHAR* szVersion = L"v1.0";  
    DWORD dwBufferSize = MAX_PATH;  
    HANDLE hDumpFile;  
    SYSTEMTIME stLocalTime;  
    MINIDUMP_EXCEPTION_INFORMATION ExpParam;  
    GetLocalTime( &stLocalTime );  
    GetTempPath( dwBufferSize, szPath );  
    StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );  
    CreateDirectory( szFileName, NULL );  
    StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",   
               szPath, szAppName, szVersion,   
               stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,   
               stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,   
               GetCurrentProcessId(), GetCurrentThreadId());  
    hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,   
                FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);  
 
    MINIDUMP_USER_STREAM UserStream[2];  
    MINIDUMP_USER_STREAM_INFORMATION UserInfo;  
    UserInfo.UserStreamCount = 1;  
    UserInfo.UserStreamArray = UserStream;  
    UserStream[0].Type = CommentStreamW;  
    UserStream[0].BufferSize = strBuild.GetLength()*sizeof(WCHAR);  
    UserStream[0].Buffer = strBuild.GetBuffer();  
    UserStream[1].Type = CommentStreamW;  
    UserStream[1].BufferSize = strError.GetLength()*sizeof(WCHAR);  
    UserStream[1].Buffer = strError.GetBuffer();  
 
    ExpParam.ThreadId = GetCurrentThreadId();  
    ExpParam.ExceptionPointers = pExceptionPointers;  
    ExpParam.ClientPointers = TRUE;  
      
    MINIDUMP_TYPE MiniDumpWithDataSegs = MiniDumpNormal   
            | MiniDumpWithHandleData   
            | MiniDumpWithUnloadedModules   
            | MiniDumpWithIndirectlyReferencedMemory   
            | MiniDumpScanMemory   
            | MiniDumpWithProcessThreadData   
            | MiniDumpWithThreadInfo;  
    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),   
                    hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);  
  // 上传mini dump 到自己服务器(略)  
  ...  
 
  return EXCEPTION_CONTINUE_SEARCH; //或者 EXCEPTION_EXECUTE_HANDLER 关闭程序  
}  
   
int _tmain()  
{  
  // 设置 execption filter  
  SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);  
  ....  
  return 0;  

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值