[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,如需转载请自行联系原作者

相关文章
|
9天前
|
Windows Python
如何反向读取Windows系统日志EVTX文件?
以下是如何反向读取Windows系统日志EVTX文件
21 2
|
1月前
|
存储 开发框架 .NET
Windows IIS中asp的global.asa全局配置文件使用说明
Windows IIS中asp的global.asa全局配置文件使用说明
37 1
|
1月前
|
Java Windows
如何在windows上运行jar包/JAR文件 如何在cmd上运行 jar包 保姆级教程 超详细
本文提供了一个详细的教程,解释了如何在Windows操作系统的命令提示符(cmd)中运行JAR文件。
888 1
|
2月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
2月前
|
Windows
[原创]用MASM32编程获取windows类型
[原创]用MASM32编程获取windows类型
|
2月前
|
JavaScript 前端开发 API
MASM32编程通过WMI获取Windows计划任务
MASM32编程通过WMI获取Windows计划任务
|
2月前
|
Windows Python
python获取windows机子上运行的程序名称
python获取windows机子上运行的程序名称
|
1月前
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
65 0
|
1月前
|
程序员 Windows
程序员必备文件搜索工具 Everything 带安装包!!! 比windows自带的文件搜索快几百倍!!! 超级好用的文件搜索工具,仅几兆,不占内存,打开即用
文章推荐了程序员必备的文件搜索工具Everything,并提供了安装包下载链接,强调其比Windows自带搜索快且占用内存少。
43 0
|
2月前
|
安全 网络安全 API
基于WMI更新Windows系统信息采集程序sysInfo的一些收获
基于WMI更新Windows系统信息采集程序sysInfo的一些收获

热门文章

最新文章