前面介绍如如何用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_FILTERlpTopLevelExceptionFilter );
BOOL WINAPI MiniDumpWriteDump( __in HANDLEhProcess, __in DWORDProcessId, __in HANDLEhFile, __in MINIDUMP_TYPEDumpType, __in PMINIDUMP_EXCEPTION_INFORMATIONExceptionParam, __in PMINIDUMP_USER_STREAM_INFORMATIONUserStreamParam, __in PMINIDUMP_CALLBACK_INFORMATIONCallbackParam );
代码示例:
[cpp]view plaincopyprint?
- #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;
- }