1 #include "StdAfx.h" 2 #include "crashtool.h" 3 4 #include <strsafe.h> 5 #include <DbgHelp.h> 6 #include <tchar.h> 7 #include "MessageDlg.h" 8 #include "Common.h" 9 #include "MusicPlayer2.h" 10 11 #pragma comment(lib, "Dbghelp.lib") 12 13 class CCrashReport 14 { 15 public: CCrashReport()16 CCrashReport() 17 { 18 GetAppPath(); 19 } ~CCrashReport()20 ~CCrashReport() {} 21 public: 22 // 生成MiniDump文件 CreateMiniDump(EXCEPTION_POINTERS * pEP)23 void CreateMiniDump(EXCEPTION_POINTERS* pEP) 24 { 25 SYSTEMTIME stLocalTime; 26 ::GetLocalTime(&stLocalTime); 27 TCHAR szDumpFile[MAX_PATH] = {0}; 28 ::StringCchPrintf(szDumpFile, _countof(szDumpFile), TEXT("%s%04d%02d%02d%02d%02d%02d_%s.dmp"), m_szDumpFilePath, 29 stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, m_szModuleFileName); 30 31 HANDLE hDumpFile; 32 hDumpFile = ::CreateFile(szDumpFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); 33 if (INVALID_HANDLE_VALUE == hDumpFile) 34 { 35 return; 36 } 37 38 m_dumpFile = szDumpFile; 39 40 MINIDUMP_EXCEPTION_INFORMATION ExpParam; 41 ExpParam.ThreadId = ::GetCurrentThreadId(); 42 ExpParam.ExceptionPointers = pEP; 43 ExpParam.ClientPointers = TRUE; 44 45 // 生成minidump文件 46 BOOL bResult = ::MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &ExpParam, NULL, NULL); 47 ::CloseHandle(hDumpFile); 48 } 49 ShowCrashInfo()50 void ShowCrashInfo() 51 { 52 // 写入错误日志 53 wstring log_info = theApp.m_str_table.LoadTextFormat(L"LOG_CRASH_ERROR", { m_dumpFile }); 54 theApp.WriteLog(log_info); 55 56 // 显示错误信息对话框 57 // 之后应改用独立的对话框,不依赖CMessageDlg 58 CMessageDlg dlg(L"CrashDlg"); 59 dlg.SetWindowTitle(theApp.m_str_table.LoadText(L"TITLE_CRASH_REPORT")); 60 dlg.SetInfoText(theApp.m_str_table.LoadText(L"TXT_CRASH_REPORT_ERROR_MESSAGE")); 61 wstring info = theApp.m_str_table.LoadTextFormat(L"TXT_CRASH_REPORT_CRASH_INFO", { m_dumpFile, theApp.GetSystemInfoString() }); 62 dlg.SetMessageText(info); 63 64 //设置图标(此功能已从CMessageDlg移除) 65 // HICON hIcon; 66 // HRESULT hr = LoadIconWithScaleDown(NULL, IDI_ERROR, theApp.DPI(32), theApp.DPI(32), &hIcon); 67 // if (SUCCEEDED(hr)) 68 // dlg.SetMessageIcon(hIcon); 69 70 dlg.DoModal(); 71 } 72 73 private: GetAppPath()74 void GetAppPath() 75 { 76 ZeroMemory(m_szModuleFileName, MAX_PATH); 77 ::GetModuleFileName(NULL, m_szDumpFilePath, _countof(m_szDumpFilePath)); 78 for (int nIndex = (int)_tcslen(m_szDumpFilePath); nIndex >= 0; --nIndex) 79 { 80 if (m_szDumpFilePath[nIndex] == TEXT('\\')) 81 { 82 ::memmove(m_szModuleFileName, m_szDumpFilePath + nIndex + 1, (int)_tcslen(m_szDumpFilePath)); 83 m_szDumpFilePath[nIndex + 1] = 0; 84 break; 85 } 86 } 87 ZeroMemory(m_szDumpFilePath, MAX_PATH); 88 if (!::GetTempPath(MAX_PATH, m_szDumpFilePath)) 89 { 90 m_szDumpFilePath[0] = _T('C'); 91 m_szDumpFilePath[1] = _T(':'); 92 m_szDumpFilePath[2] = _T('\\'); 93 m_szDumpFilePath[3] = _T('\0'); 94 } 95 } 96 private: 97 wchar_t m_szDumpFilePath[MAX_PATH]; 98 wchar_t m_szModuleFileName[MAX_PATH]; 99 100 CString m_dumpFile; 101 }; 102 103 namespace CRASHREPORT 104 { __UnhandledExceptionFilter(PEXCEPTION_POINTERS pEP)105 static LONG WINAPI __UnhandledExceptionFilter(PEXCEPTION_POINTERS pEP) 106 { 107 ::SetErrorMode(0); //使用默认的 108 CCrashReport cr; 109 cr.CreateMiniDump(pEP); 110 cr.ShowCrashInfo(); 111 return EXCEPTION_CONTINUE_SEARCH; 112 } 113 StartCrashReport()114 void StartCrashReport() 115 { 116 ::SetUnhandledExceptionFilter(__UnhandledExceptionFilter); 117 } 118 } 119