[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;   



 本文转自 陈本峰 51CTO博客,原文链接:http://blog.51cto.com/wingeek/273979,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值