AutoDmp.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "StdAfx.h"
  2. #include "AutoDmp.h"
  3. #include <string>
  4. #include <sstream>
  5. //-----------------dmp文件生成相关--------------------------------------------
  6. using namespace std;
  7. #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x00000004)
  8. #define MiniDumpWithThreadInfo 0x1000
  9. typedef BOOL(WINAPI *PGetModuleHandleEx)(DWORD dwFlags, LPCTSTR lpModuleName, HMODULE *phModule);
  10. string GetProcessDirectoryDump()
  11. {
  12. string ret = "";
  13. char szFilename[MAX_PATH] = { 0 };
  14. DWORD res = GetModuleFileNameA(0, szFilename, MAX_PATH);
  15. if (res == 0)
  16. {
  17. return ret;
  18. }
  19. string fullpath = szFilename;
  20. string::size_type firstHit = fullpath.find_last_of('\\');
  21. if (firstHit == string::npos || firstHit == 0)
  22. {
  23. return ret;
  24. }
  25. ret = fullpath.substr(0, firstHit);//kick last \
  26. return ret;
  27. }
  28. VOID CreateDump(struct _EXCEPTION_POINTERS *pExceptionPointers)
  29. {
  30. //收集信息
  31. string strBuild;
  32. unsigned int ret1 = 0;
  33. HANDLE hDumpFile;
  34. std::stringstream strm;
  35. strm << "Build: " << __DATE__ << " " << __TIME__;
  36. strm >> strBuild;
  37. //strBuild.Format(L"Build: %s %s", __DATE__, __TIME__);
  38. string strError;
  39. HMODULE hModule;
  40. char szModuleName[MAX_PATH] = { 0 };
  41. GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, &hModule);
  42. GetModuleFileName(hModule, szModuleName, ARRAYSIZE(szModuleName));
  43. strm.clear();
  44. strm << szModuleName << ", " << pExceptionPointers->ExceptionRecord->ExceptionCode << ", " << pExceptionPointers->ExceptionRecord->ExceptionFlags << ", " << pExceptionPointers->ExceptionRecord->ExceptionAddress;
  45. strm >> strError;
  46. //生成 mini crash dump
  47. BOOL bMiniDumpSuccessful;
  48. DWORD dwBufferSize = MAX_PATH;
  49. SYSTEMTIME stLocalTime;
  50. MINIDUMP_EXCEPTION_INFORMATION ExpParam;
  51. GetLocalTime(&stLocalTime);
  52. char szFileName[MAX_PATH] = { 0 };
  53. sprintf_s(szFileName, MAX_PATH, "%04d%02d%02d-%02d%02d%02d-ProcessID[%ld]-ThreadID[%ld].dmp",
  54. stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
  55. stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
  56. GetCurrentProcessId(), GetCurrentThreadId());
  57. std::string strDmppath = GetProcessDirectoryDump();
  58. strDmppath += string("\\");
  59. strDmppath.append(szFileName);
  60. hDumpFile = CreateFile(strDmppath.c_str(), GENERIC_READ | GENERIC_WRITE,
  61. FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
  62. MINIDUMP_USER_STREAM UserStream[2];
  63. MINIDUMP_USER_STREAM_INFORMATION UserInfo;
  64. UserInfo.UserStreamCount = 1;
  65. UserInfo.UserStreamArray = UserStream;
  66. UserStream[0].Type = CommentStreamA;
  67. UserStream[0].BufferSize = strBuild.size();
  68. UserStream[0].Buffer = (PVOID)strBuild.c_str();
  69. UserStream[1].Type = CommentStreamA;
  70. UserStream[1].BufferSize = strError.size();
  71. UserStream[1].Buffer = (PVOID)strError.c_str();
  72. ExpParam.ThreadId = GetCurrentThreadId();
  73. ExpParam.ExceptionPointers = pExceptionPointers;
  74. ExpParam.ClientPointers = TRUE;
  75. MINIDUMP_TYPE MiniDumpWithDataSegs = (MINIDUMP_TYPE)(MiniDumpNormal
  76. | MiniDumpWithHandleData
  77. | MiniDumpWithUnloadedModules
  78. | MiniDumpWithIndirectlyReferencedMemory
  79. | MiniDumpScanMemory
  80. | MiniDumpWithProcessThreadData
  81. | MiniDumpWithThreadInfo);
  82. bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
  83. hDumpFile, MiniDumpWithDataSegs, &ExpParam, &UserInfo, NULL);
  84. return;
  85. }
  86. LONG WINAPI AutoDmp::NewUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *lpExceptionInfo)
  87. {
  88. CreateDump(lpExceptionInfo);
  89. return EXCEPTION_EXECUTE_HANDLER;
  90. }
  91. AutoDmp::AutoDmp()
  92. {
  93. SetUnhandledExceptionFilter(NewUnhandledExceptionFilter);
  94. }
  95. AutoDmp::~AutoDmp()
  96. {
  97. }
  98. //dmp生成参考资料
  99. //http://www.sjsjw.com/kf_other/article/031086ABA018049.asp
  100. //在win7 64bit + vs2008 + sdk v7.0的环境下编译Detours
  101. //http://blog.csdn.net/genesisbible/article/details/6771988
  102. //下载编译好的Detours
  103. //http://download.csdn.net/download/staver102/7648875
  104. //DMP文件的使用:
  105. //把dmp文件和exe, pdb文件放在同一目录下, 然后用编译器(如vc)打开, 然后开始调试就会中断到刚才中断的地方.
  106. //使用符号服务器
  107. //您可以使用符号服务器自动下载用于调试 Visual Studio .NET 项目的正确符号。
  108. //Microsoft 在 http://msdl.microsoft.com/download/symbols 上为开发人员维护了一个公共符号服务器。
  109. //此服务器为各种操作系统(Windows NT 4.0、Windows 2000、Windows XP 和 Windows Server 2003)、MDAC、IIS、ISA 和 .NET Framework 提供符号。
  110. //
  111. //另外,您也可以将本地符号服务器安装在 Intranet 上或本地计算机上。
  112. //要使用符号服务器,必须在项目中指定正确的服务器路径。
  113. //
  114. //设置符号服务器的路径
  115. //1.在 Visual Studio 中打开该项目。
  116. //2.在“解决方案资源管理器”视图中选择解决方案的名称。
  117. //3.从“项目”菜单中选择“设置启动项目”。
  118. //4.在“解决方案 <项目> 属性页”对话框中,打开“通用属性”文件夹,单击“调试符号文件”。
  119. //5.在“在这些路径中搜索符号文件”框中创建新的行,方法是双击空的新行或单击“新建行”按钮。
  120. //6.在新行中输入符号服务器的路径。
  121. //若要使用 Microsoft 公共符号服务器,请输入:
  122. //srv*c:\cache*http://msdl.microsoft.com/download/symbols;
  123. //若要使用 Intranet 符号服务器,请输入:
  124. //srv*\\server\path\symbols;
  125. //若要使用本地计算机上的符号服务器,请输入:
  126. //c:\path\symbols;
  127. //7.不要单击“检查项”按钮。
  128. //8.单击“确定”按钮。
  129. //9.将 symsrv.dll 从 Visual Studio .NET 安装盘复制到 C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE。
  130. //-----------------dmp文件生成相关--------------------------------------------