123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #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 <string>
- #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文件生成相关--------------------------------------------
|