#include "StdAfx.h" #include "AutoDmp.h" //-----------------dmp文件生成相关-------------------------------------------- #include "detours.h" #ifndef _WIN64 #pragma comment(lib, "AutoDmp\\lib.X86\\detours.lib") #else #pragma comment(lib, "AutoDmp\\lib.X64\\detours.lib") #endif #include #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x00000004) #define MiniDumpWithThreadInfo 0x1000 typedef BOOL(WINAPI *PGetModuleHandleEx)(DWORD dwFlags, LPCTSTR lpModuleName, HMODULE *phModule); VOID CreateDump(struct _EXCEPTION_POINTERS *pExceptionPointers) { //收集信息 CStringW strBuild; strBuild.Format(L"Build: %s %s", __DATE__, __TIME__); CStringW strError; HMODULE hModule; WCHAR szModuleName[MAX_PATH] = { 0 }; PGetModuleHandleEx pFun = (PGetModuleHandleEx)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), _T("GetModuleHandleExW")); if (!pFun) { return; } pFun(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, &hModule); GetModuleFileNameW(hModule, szModuleName, ARRAYSIZE(szModuleName)); std::wstring strDmppath = szModuleName; size_t index = strDmppath.rfind(L'.'); strDmppath = strDmppath.substr(0, index); strDmppath.append(L"_Dmpfile"); strError.Format(L"%s %d , %d ,%d.", szModuleName, pExceptionPointers->ExceptionRecord->ExceptionCode, pExceptionPointers->ExceptionRecord->ExceptionFlags, pExceptionPointers->ExceptionRecord->ExceptionAddress); CreateDirectoryW(strDmppath.c_str(), NULL); //生成 mini crash dump BOOL bMiniDumpSuccessful; DWORD dwBufferSize = MAX_PATH; HANDLE hDumpFile; SYSTEMTIME stLocalTime; MINIDUMP_EXCEPTION_INFORMATION ExpParam; GetLocalTime(&stLocalTime); WCHAR szFileName[MAX_PATH]; swprintf_s(szFileName, MAX_PATH, L"%04d%02d%02d-%02d%02d%02d-ProcessID[%ld]-ThreadID[%ld].dmp", stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); strDmppath += L'\\'; strDmppath.append(szFileName); hDumpFile = CreateFileW(strDmppath.c_str(), 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 = (MINIDUMP_TYPE)(MiniDumpNormal | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory | MiniDumpWithProcessThreadData | MiniDumpWithThreadInfo); bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL); return; } LONG WINAPI AutoDmp::NewUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *lpExceptionInfo) { OutputDebugString(_T("NewUnhandledExceptionFilter\n")); CreateDump(lpExceptionInfo); return EXCEPTION_EXECUTE_HANDLER; } AutoDmp::AutoDmp() { m_lpUnhandledExceptionFilter = NULL; do { SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); m_lpUnhandledExceptionFilter = DetourFindFunction("KERNEL32.DLL", "UnhandledExceptionFilter"); if (NULL == m_lpUnhandledExceptionFilter) { break; } LONG lRes = NO_ERROR; lRes = DetourTransactionBegin(); if (NO_ERROR != lRes) { break; } lRes = DetourAttach(&m_lpUnhandledExceptionFilter, NewUnhandledExceptionFilter); if (NO_ERROR != lRes) { break; } lRes = DetourTransactionCommit(); if (NO_ERROR != lRes) { break; } } while (0); } AutoDmp::~AutoDmp() { if (m_lpUnhandledExceptionFilter) { do { LONG lRes = NO_ERROR; lRes = DetourTransactionBegin(); if (NO_ERROR != lRes) { break; } lRes = DetourDetach(&m_lpUnhandledExceptionFilter, NewUnhandledExceptionFilter); if (NO_ERROR != lRes) { break; } lRes = DetourTransactionCommit(); if (NO_ERROR != lRes) { break; } } while (0); } } //dmp生成参考资料 //http://www.sjsjw.com/kf_other/article/031086ABA018049.asp //在win7 64bit + vs2008 + sdk v7.0的环境下编译Detours //http://blog.csdn.net/genesisbible/article/details/6771988 //下载编译好的Detours //http://download.csdn.net/download/staver102/7648875 //DMP文件的使用: //把dmp文件和exe, pdb文件放在同一目录下, 然后用编译器(如vc)打开, 然后开始调试就会中断到刚才中断的地方. //使用符号服务器 //您可以使用符号服务器自动下载用于调试 Visual Studio .NET 项目的正确符号。 //Microsoft 在 http://msdl.microsoft.com/download/symbols 上为开发人员维护了一个公共符号服务器。 //此服务器为各种操作系统(Windows NT 4.0、Windows 2000、Windows XP 和 Windows Server 2003)、MDAC、IIS、ISA 和 .NET Framework 提供符号。 // //另外,您也可以将本地符号服务器安装在 Intranet 上或本地计算机上。 //要使用符号服务器,必须在项目中指定正确的服务器路径。 // //设置符号服务器的路径 //1.在 Visual Studio 中打开该项目。 //2.在“解决方案资源管理器”视图中选择解决方案的名称。 //3.从“项目”菜单中选择“设置启动项目”。 //4.在“解决方案 <项目> 属性页”对话框中,打开“通用属性”文件夹,单击“调试符号文件”。 //5.在“在这些路径中搜索符号文件”框中创建新的行,方法是双击空的新行或单击“新建行”按钮。 //6.在新行中输入符号服务器的路径。 //若要使用 Microsoft 公共符号服务器,请输入: //srv*c:\cache*http://msdl.microsoft.com/download/symbols; //若要使用 Intranet 符号服务器,请输入: //srv*\\server\path\symbols; //若要使用本地计算机上的符号服务器,请输入: //c:\path\symbols; //7.不要单击“检查项”按钮。 //8.单击“确定”按钮。 //9.将 symsrv.dll 从 Visual Studio .NET 安装盘复制到 C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE。 //-----------------dmp文件生成相关--------------------------------------------