xref: /MusicPlayer2/MusicPlayer2/crashtool.cpp (revision 9c4ef8a8f2876557772f84b85d0eb04ab8fa8c61)
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