// create_dump.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include "create_dump.h" //// 这是导出变量的一个示例 //CREATE_DUMP_API int ncreate_dump=0; // //// 这是导出函数的一个示例。 //CREATE_DUMP_API int fncreate_dump(void) //{ // return 42; //} // //// 这是已导出类的构造函数。 //// 有关类定义的信息,请参阅 create_dump.h //Ccreate_dump::Ccreate_dump() //{ // return; //} #include "stdafx.h" #include #include "create_dump.h" #include #include #include #ifndef STATUS_INVALID_CRUNTIME_PARAMETER #define STATUS_INVALID_CRUNTIME_PARAMETER ((DWORD )0xC0000417L) #endif #pragma comment(lib, "shlwapi.lib") typedef BOOL (_stdcall *tMiniDumpWriteDump)( HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam ); static tMiniDumpWriteDump pMiniDumpWriteDump; // Global class instance // static CExceptionReport ExceptionReport; LPTOP_LEVEL_EXCEPTION_FILTER CExceptionReport::m_previousExceptionFilter = NULL; TCHAR CExceptionReport::m_pDmpFileName[MAX_PATH] = { 0 }; HANDLE CExceptionReport::m_hDumpFile = INVALID_HANDLE_VALUE; BOOL CExceptionReport::m_bFirstRun = TRUE; _invalid_parameter_handler CExceptionReport::s_fnInvalidParameterHandler = NULL; CExceptionReport::CExceptionReport() { m_bFirstRun = TRUE; m_previousExceptionFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter); s_fnInvalidParameterHandler = _set_invalid_parameter_handler(&InvalidParameterHandler); // Retrieve report/dump filenames TCHAR FullPath[MAX_PATH] = { 0 }; GetModuleFileName(0, FullPath, MAX_PATH); ::PathRemoveExtension(FullPath); RSExecptionTString time = FormatCurrentTimeString(); _tcscat_s(FullPath, MAX_PATH, time.c_str()); _tcscpy_s(m_pDmpFileName, MAX_PATH, FullPath); _tcscat_s(m_pDmpFileName, MAX_PATH, _T(".dmp")); } CExceptionReport::~CExceptionReport() { SetUnhandledExceptionFilter(m_previousExceptionFilter); } LONG WINAPI CExceptionReport::UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo) { if (!m_bFirstRun) { // Don't generate exception report twice if (m_previousExceptionFilter) return m_previousExceptionFilter(pExceptionInfo); else return EXCEPTION_CONTINUE_SEARCH; } else m_bFirstRun = FALSE; HMODULE hDll = LoadLibrary(_T("dbghelp.dll")); if (!hDll) { if (m_previousExceptionFilter) return m_previousExceptionFilter(pExceptionInfo); else return EXCEPTION_CONTINUE_SEARCH; } //加载写dmp函数 pMiniDumpWriteDump = (tMiniDumpWriteDump)GetProcAddress(hDll, "MiniDumpWriteDump"); if (pMiniDumpWriteDump == NULL) { FreeLibrary(hDll); if (m_previousExceptionFilter) return m_previousExceptionFilter(pExceptionInfo); else return EXCEPTION_CONTINUE_SEARCH; } // Suspend all threads to freeze the current state SuspendThreads(); //真正的写dmp文件 m_hDumpFile = CreateFile(m_pDmpFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0); if (m_hDumpFile == INVALID_HANDLE_VALUE) { TCHAR tmp[MAX_PATH]; _tcscpy_s(tmp, MAX_PATH, m_pDmpFileName); TCHAR *pos = _tcsrchr(tmp, _T('\\')); if (pos) { pos++; _stprintf_s(m_pDmpFileName, MAX_PATH, _T("c:\\%s"), pos); } else _stprintf_s(m_pDmpFileName, MAX_PATH, _T("c:\\%s"), tmp); m_hDumpFile = CreateFile(m_pDmpFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0); } int nError = 0; #ifdef TRY TRY #endif { if (m_hDumpFile != INVALID_HANDLE_VALUE) writeMiniDump(pExceptionInfo); CloseHandle(m_hDumpFile); nError = 0; } #ifdef TRY CATCH_ALL(e); { CloseHandle(m_hDumpFile); } END_CATCH_ALL #endif if (nError)//happens some errors { } else //the exception report has been saved { FreeLibrary(hDll); return EXCEPTION_CONTINUE_SEARCH; } FreeLibrary(hDll); if (m_previousExceptionFilter) return m_previousExceptionFilter(pExceptionInfo); else return EXCEPTION_CONTINUE_SEARCH; } bool CExceptionReport::writeMiniDump(PEXCEPTION_POINTERS pExceptionInfo) { // Write the minidump to the file MINIDUMP_EXCEPTION_INFORMATION eInfo; eInfo.ThreadId = GetCurrentThreadId(); eInfo.ExceptionPointers = pExceptionInfo; eInfo.ClientPointers = FALSE; MINIDUMP_CALLBACK_INFORMATION cbMiniDump; cbMiniDump.CallbackRoutine = 0; cbMiniDump.CallbackParam = 0; pMiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), m_hDumpFile, MiniDumpNormal, pExceptionInfo ? &eInfo : NULL, NULL, &cbMiniDump); // Close file CloseHandle(m_hDumpFile); return true; } void CExceptionReport::SuspendThreads() { // Try to get OpenThread and Thread32* function from kernel32.dll, since it's not available on Win95/98 typedef HANDLE(WINAPI *tOpenThread) (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId); typedef BOOL(WINAPI *tThread32First) (HANDLE hSnapshot, LPTHREADENTRY32 lpte); typedef BOOL(WINAPI *tThread32Next) (HANDLE hSnapshot, LPTHREADENTRY32 lpte); typedef HANDLE(WINAPI *tCreateToolhelp32Snapshot) (DWORD dwFlags, DWORD th32ProcessID); HMODULE hKernel32Dll = GetModuleHandle(_T("kernel32.dll")); if (!hKernel32Dll) return; tOpenThread pOpenThread = (tOpenThread)GetProcAddress(hKernel32Dll, "OpenThread"); tThread32First pThread32First = (tThread32First)GetProcAddress(hKernel32Dll, "Thread32First"); tThread32Next pThread32Next = (tThread32Next)GetProcAddress(hKernel32Dll, "Thread32Next"); tCreateToolhelp32Snapshot pCreateToolhelp32Snapshot = (tCreateToolhelp32Snapshot)GetProcAddress(hKernel32Dll, "CreateToolhelp32Snapshot"); if (!pOpenThread || !pThread32First || !pThread32Next || !pCreateToolhelp32Snapshot) { return; } HANDLE hSnapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); // Get information about own process/thread DWORD ownProcessId = GetCurrentProcessId(); DWORD ownThreadId = GetCurrentThreadId(); // Enumerate threads THREADENTRY32 entry; entry.dwSize = sizeof(THREADENTRY32); BOOL bNext = pThread32First(hSnapshot, &entry); while (bNext) { if (entry.th32OwnerProcessID == ownProcessId && entry.th32ThreadID != ownThreadId) { // Suspen threads of own process HANDLE hThread = pOpenThread(THREAD_SUSPEND_RESUME, FALSE, entry.th32ThreadID); if (hThread) SuspendThread(hThread); } bNext = pThread32Next(hSnapshot, &entry); } } const RSExecptionTString CExceptionReport::FormatCurrentTimeString() { SYSTEMTIME st; GetLocalTime(&st); TCHAR szDateTime[1024]; memset(szDateTime, 0, sizeof(szDateTime)); _stprintf_s(szDateTime, 1024, _T("%04d-%02d-%02d(%02d-%02d-%02d)"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); return RSExecptionTString(szDateTime); } void CExceptionReport::InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) { RaiseException(STATUS_INVALID_CRUNTIME_PARAMETER, 0, 0, NULL); // 抛异常, 生成dump文件 }