转载:https://www.easyicon.net/(免费icon)
转载:https://www.codeproject.com/Articles/5260/XCrashReport-Exception-Handling-and-Crash-Report-4(codeproject示例demo)
转载:https://blog.csdn.net/agan4014/article/details/2614770
转载:http://blog.sina.com.cn/s/blog_5513eb7b0100nu80.html
转载:https://blog.csdn.net/sunflover454/article/details/51200663
实现原理:在程序运行过程中异常,通过捕获异常,并在回调函数启动BugReport程序
实现效果
第一步:导入上面的源码文件到自己的工程中
CrashFileNames.h
#ifndef CRASHFILENAMES_H #define CRASHFILENAMES_H #define XCRASHREPORT_MINI_DUMP_FILE _T("CRASH.DMP")//Crash文件 #define XCRASHREPORT_ERROR_LOG_FILE _T("ERRORLOG.TXT")//日志文件 #define XCRASHREPORT_CRASH_REPORT_APP _T("xxxBugReport.exe")//你自己BugReport程序名字 #endif //CRASHFILENAMES_H
ExceptionHandler.h
#ifndef EXCEPTIONHANDLER_H #define EXCEPTIONHANDLER_H typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS data, const TCHAR *Message); #endif
ExceptionHandler.cpp
#pragma warning(disable : 4514) #pragma warning(disable : 4201) #define _WIN32_WINDOWS 0x0500 // for IsDebuggerPresent // comment out this line if you don't want minidumps #define XCRASHREPORT_WRITE_MINIDUMP //#define XCRASHREPORT_WRITE_ERROR_LOG // does not require MFC; use 'Not using precompiled headers' #include "windows.h" #include <tchar.h> #include "GetWinVer.h" #include "miniversion.h" #include <DbgHelp.h> #include "CrashFileNames.h" #pragma comment(lib, "Dbghelp.lib") #ifndef _countof #define _countof(array) (sizeof(array)/sizeof(array[0])) #endif const int NumCodeBytes = 16; // Number of code bytes to record. const int MaxStackDump = 3072; // Maximum number of DWORDS in stack dumps. const int StackColumns = 4; // Number of columns in stack dump. #define ONEK 1024 #define SIXTYFOURK (64*ONEK) #define ONEM (ONEK*ONEK) #define ONEG (ONEK*ONEK*ONEK) /// // lstrrchr (avoid the C Runtime ) static TCHAR * lstrrchr(LPCTSTR string, int ch) { TCHAR *start = (TCHAR *)string; while (*string++) /* find end of string */ ; /* search towards front */ while (--string != start && *string != (TCHAR) ch) ; if (*string == (TCHAR) ch) /* char found ? */ return (TCHAR *)string; return NULL; } #define HPRINTF_BUFFER_SIZE (8*1024) // must be at least 2048 static TCHAR hprintf_buffer[HPRINTF_BUFFER_SIZE]; // wvsprintf never prints more than one K. static int hprintf_index = 0; /// // hflush static void hflush(HANDLE LogFile) { if (hprintf_index > 0) { DWORD NumBytes; WriteFile(LogFile, hprintf_buffer, lstrlen(hprintf_buffer), &NumBytes, 0); hprintf_index = 0; } } /// // hprintf static void hprintf(HANDLE LogFile, LPCTSTR Format, ...) { if (hprintf_index > (HPRINTF_BUFFER_SIZE-1024)) { DWORD NumBytes; WriteFile(LogFile, hprintf_buffer, lstrlen(hprintf_buffer), &NumBytes, 0); hprintf_index = 0; } va_list arglist; va_start( arglist, Format); hprintf_index += wvsprintf(&hprintf_buffer[hprintf_index], Format, arglist); va_end( arglist); } #ifdef XCRASHREPORT_WRITE_MINIDUMP /// // DumpMiniDump static void DumpMiniDump(HANDLE hFile, PEXCEPTION_POINTERS excpInfo) { if (excpInfo == NULL) { // Generate exception to get proper context in dump __try { OutputDebugString(_T("raising exception\r\n")); RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL); } __except(DumpMiniDump(hFile, GetExceptionInformation()), EXCEPTION_CONTINUE_EXECUTION) { } } else { OutputDebugString(_T("writing minidump\r\n")); MINIDUMP_EXCEPTION_INFORMATION eInfo; eInfo.ThreadId = GetCurrentThreadId(); eInfo.ExceptionPointers = excpInfo; eInfo.ClientPointers = FALSE; // note: MiniDumpWithIndirectlyReferencedMemory does not work on Win98 MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, excpInfo ? &eInfo : NULL, NULL, NULL); } } #endif // XCRASHREPORT_WRITE_MINIDUMP /// // FormatTime // // Format the specified FILETIME to output in a human readable format, // without using the C run time. static void FormatTime(LPTSTR output, FILETIME TimeToPrint) { output[0] = _T('\0'); WORD Date, Time; if (FileTimeToLocalFileTime(&TimeToPrint, &TimeToPrint) && FileTimeToDosDateTime(&TimeToPrint, &Date, &Time)) { wsprintf(output, _T("%d/%d/%d %02d:%02d:%02d"), (Date / 32) & 15, Date & 31, (Date / 512) + 1980, (Time >> 11), (Time >> 5) & 0x3F, (Time & 0x1F) * 2); } } /// // DumpModuleInfo // // Print information about a code module (DLL or EXE) such as its size, // location, time stamp, etc. static bool DumpModuleInfo(HANDLE LogFile, HINSTANCE ModuleHandle, int nModuleNo) { bool rc = false; TCHAR szModName[MAX_PATH*2]; ZeroMemory(szModName, sizeof(szModName)); __try { if (GetModuleFileName(ModuleHandle, szModName, sizeof(szModName)-2) > 0) { // If GetModuleFileName returns greater than zero then this must // be a valid code module address. Therefore we can try to walk // our way through its structures to find the link time stamp. IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle; if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic) return false; IMAGE_NT_HEADERS *NTHeader = (IMAGE_NT_HEADERS*)((TCHAR *)DosHeader + DosHeader->e_lfanew); if (IMAGE_NT_SIGNATURE != NTHeader->Signature) return false; // open the code module file so that we can get its file date and size HANDLE ModuleFile = CreateFile(szModName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); TCHAR TimeBuffer[100]; TimeBuffer[0] = _T('\0'); DWORD FileSize = 0; if (ModuleFile != INVALID_HANDLE_VALUE) { FileSize = GetFileSize(ModuleFile, 0); FILETIME LastWriteTime; if (GetFileTime(ModuleFile, 0, 0, &LastWriteTime)) { FormatTime(TimeBuffer, LastWriteTime); } CloseHandle(ModuleFile); } hprintf(LogFile, _T("Module %d\r\n"), nModuleNo); hprintf(LogFile, _T("%s\r\n"), szModName); hprintf(LogFile, _T("Image Base: 0x%08x Image Size: 0x%08x\r\n"), NTHeader->OptionalHeader.ImageBase, NTHeader->OptionalHeader.SizeOfImage), hprintf(LogFile, _T("Checksum: 0x%08x Time Stamp: 0x%08x\r\n"), NTHeader->OptionalHeader.CheckSum, NTHeader->FileHeader.TimeDateStamp); hprintf(LogFile, _T("File Size: %-10d File Time: %s\r\n"), FileSize, TimeBuffer); hprintf(LogFile, _T("Version Information:\r\n")); CMiniVersion ver(szModName); TCHAR szBuf[200]; WORD dwBuf[4]; ver.GetCompanyName(szBuf, sizeof(szBuf)-1); hprintf(LogFile, _T(" Company: %s\r\n"), szBuf); ver.GetProductName(szBuf, sizeof(szBuf)-1); hprintf(LogFile, _T(" Product: %s\r\n"), szBuf); ver.GetFileDescription(szBuf, sizeof(szBuf)-1); hprintf(LogFile, _T(" FileDesc: %s\r\n"), szBuf); ver.GetFileVersion(dwBuf); hprintf(LogFile, _T(" FileVer: %d.%d.%d.%d\r\n"), dwBuf[0], dwBuf[1], dwBuf[2], dwBuf[3]); ver.GetProductVersion(dwBuf); hprintf(LogFile, _T(" ProdVer: %d.%d.%d.%d\r\n"), dwBuf[0], dwBuf[1], dwBuf[2], dwBuf[3]); ver.Release(); hprintf(LogFile, _T("\r\n")); rc = true; } } // Handle any exceptions by continuing from this point. __except(EXCEPTION_EXECUTE_HANDLER) { } return rc; } /// // DumpModuleList // // Scan memory looking for code modules (DLLs or EXEs). VirtualQuery is used // to find all the blocks of address space that were reserved or committed, // and ShowModuleInfo will display module information if they are code // modules. static void DumpModuleList(HANDLE LogFile) { SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); const size_t PageSize = SystemInfo.dwPageSize; // Set NumPages to the number of pages in the 4GByte address space, // while being careful to avoid overflowing ints const size_t NumPages = 4 * size_t(ONEG / PageSize); size_t pageNum = 0; void *LastAllocationBase = 0; int nModuleNo = 1; while (pageNum < NumPages) { MEMORY_BASIC_INFORMATION MemInfo; if (VirtualQuery((void *)(pageNum * PageSize), &MemInfo, sizeof(MemInfo))) { if (MemInfo.RegionSize > 0) { // Adjust the page number to skip over this block of memory pageNum += MemInfo.RegionSize / PageSize; if (MemInfo.State == MEM_COMMIT && MemInfo.AllocationBase > LastAllocationBase) { // Look for new blocks of committed memory, and try // recording their module names - this will fail // gracefully if they aren't code modules LastAllocationBase = MemInfo.AllocationBase; if (DumpModuleInfo(LogFile, (HINSTANCE)LastAllocationBase, nModuleNo)) { nModuleNo++; } } } else pageNum += SIXTYFOURK / PageSize; } else pageNum += SIXTYFOURK / PageSize; // If VirtualQuery fails we advance by 64K because that is the // granularity of address space doled out by VirtualAlloc() } } /// // DumpSystemInformation // // Record information about the user's system, such as processor type, amount // of memory, etc. static void DumpSystemInformation(HANDLE LogFile) { FILETIME CurrentTime; GetSystemTimeAsFileTime(&CurrentTime); TCHAR szTimeBuffer[100]; FormatTime(szTimeBuffer, CurrentTime); hprintf(LogFile, _T("Error occurred at %s.\r\n"), szTimeBuffer); TCHAR szModuleName[MAX_PATH*2]; ZeroMemory(szModuleName, sizeof(szModuleName)); if (GetModuleFileName(0, szModuleName, _countof(szModuleName)-2) <= 0) lstrcpy(szModuleName, _T("Unknown")); TCHAR szUserName[200]; ZeroMemory(szUserName, sizeof(szUserName)); DWORD UserNameSize = _countof(szUserName)-2; if (!GetUserName(szUserName, &UserNameSize)) lstrcpy(szUserName, _T("Unknown")); hprintf(LogFile, _T("%s, run by %s.\r\n"), szModuleName, szUserName); // print out operating system TCHAR szWinVer[50], szMajorMinorBuild[50]; int nWinVer; GetWinVer(szWinVer, &nWinVer, szMajorMinorBuild); hprintf(LogFile, _T("Operating system: %s (%s).\r\n"), szWinVer, szMajorMinorBuild); SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); hprintf(LogFile, _T("%d processor(s), type %d.\r\n"), SystemInfo.dwNumberOfProcessors, SystemInfo.dwProcessorType); MEMORYSTATUS MemInfo; MemInfo.dwLength = sizeof(MemInfo); GlobalMemoryStatus(&MemInfo); // Print out info on memory, rounded up. hprintf(LogFile, _T("%d%% memory in use.\r\n"), MemInfo.dwMemoryLoad); hprintf(LogFile, _T("%d MBytes physical memory.\r\n"), (MemInfo.dwTotalPhys + ONEM - 1) / ONEM); hprintf(LogFile, _T("%d MBytes physical memory free.\r\n"), (MemInfo.dwAvailPhys + ONEM - 1) / ONEM); hprintf(LogFile, _T("%d MBytes paging file.\r\n"), (MemInfo.dwTotalPageFile + ONEM - 1) / ONEM); hprintf(LogFile, _T("%d MBytes paging file free.\r\n"), (MemInfo.dwAvailPageFile + ONEM - 1) / ONEM); hprintf(LogFile, _T("%d MBytes user address space.\r\n"), (MemInfo.dwTotalVirtual + ONEM - 1) / ONEM); hprintf(LogFile, _T("%d MBytes user address space free.\r\n"), (MemInfo.dwAvailVirtual + ONEM - 1) / ONEM); } /// // GetExceptionDescription // // Translate the exception code into something human readable static const TCHAR *GetExceptionDescription(DWORD ExceptionCode) { struct ExceptionNames { DWORD ExceptionCode; TCHAR * ExceptionName; }; #if 0 // from winnt.h #define STATUS_WAIT_0 ((DWORD )0x00000000L) #define STATUS_ABANDONED_WAIT_0 ((DWORD )0x00000080L) #define STATUS_USER_APC ((DWORD )0x000000C0L) #define STATUS_TIMEOUT ((DWORD )0x00000102L) #define STATUS_PENDING ((DWORD )0x00000103L) #define STATUS_SEGMENT_NOTIFICATION ((DWORD )0x40000005L) #define STATUS_GUARD_PAGE_VIOLATION ((DWORD )0x80000001L) #define STATUS_DATATYPE_MISALIGNMENT ((DWORD )0x80000002L) #define STATUS_BREAKPOINT ((DWORD )0x80000003L) #define STATUS_SINGLE_STEP ((DWORD )0x80000004L) #define STATUS_ACCESS_VIOLATION ((DWORD )0xC0000005L) #define STATUS_IN_PAGE_ERROR ((DWORD )0xC0000006L) #define STATUS_INVALID_HANDLE ((DWORD )0xC0000008L) #define STATUS_NO_MEMORY ((DWORD )0xC0000017L) #define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL) #define STATUS_NONCONTINUABLE_EXCEPTION ((DWORD )0xC0000025L) #define STATUS_INVALID_DISPOSITION ((DWORD )0xC0000026L) #define STATUS_ARRAY_BOUNDS_EXCEEDED ((DWORD )0xC000008CL) #define STATUS_FLOAT_DENORMAL_OPERAND ((DWORD )0xC000008DL) #define STATUS_FLOAT_DIVIDE_BY_ZERO ((DWORD )0xC000008EL) #define STATUS_FLOAT_INEXACT_RESULT ((DWORD )0xC000008FL) #define STATUS_FLOAT_INVALID_OPERATION ((DWORD )0xC0000090L) #define STATUS_FLOAT_OVERFLOW ((DWORD )0xC0000091L) #define STATUS_FLOAT_STACK_CHECK ((DWORD )0xC0000092L) #define STATUS_FLOAT_UNDERFLOW ((DWORD )0xC0000093L) #define STATUS_INTEGER_DIVIDE_BY_ZERO ((DWORD )0xC0000094L) #define STATUS_INTEGER_OVERFLOW ((DWORD )0xC0000095L) #define STATUS_PRIVILEGED_INSTRUCTION ((DWORD )0xC0000096L) #define STATUS_STACK_OVERFLOW ((DWORD )0xC00000FDL) #define STATUS_CONTROL_C_EXIT ((DWORD )0xC000013AL) #define STATUS_FLOAT_MULTIPLE_FAULTS ((DWORD )0xC00002B4L) #define STATUS_FLOAT_MULTIPLE_TRAPS ((DWORD )0xC00002B5L) #define STATUS_ILLEGAL_VLM_REFERENCE ((DWORD )0xC00002C0L) #endif ExceptionNames ExceptionMap[] = { {0x40010005, _T("a Control-C")}, {0x40010008, _T("a Control-Break")}, {0x80000002, _T("a Datatype Misalignment")}, {0x80000003, _T("a Breakpoint")}, {0xc0000005, _T("an Access Violation")}, {0xc0000006, _T("an In Page Error")}, {0xc0000017, _T("a No Memory")}, {0xc000001d, _T("an Illegal Instruction")}, {0xc0000025, _T("a Noncontinuable Exception")}, {0xc0000026, _T("an Invalid Disposition")}, {0xc000008c, _T("a Array Bounds Exceeded")}, {0xc000008d, _T("a Float Denormal Operand")}, {0xc000008e, _T("a Float Divide by Zero")}, {0xc000008f, _T("a Float Inexact Result")}, {0xc0000090, _T("a Float Invalid Operation")}, {0xc0000091, _T("a Float Overflow")}, {0xc0000092, _T("a Float Stack Check")}, {0xc0000093, _T("a Float Underflow")}, {0xc0000094, _T("an Integer Divide by Zero")}, {0xc0000095, _T("an Integer Overflow")}, {0xc0000096, _T("a Privileged Instruction")}, {0xc00000fD, _T("a Stack Overflow")}, {0xc0000142, _T("a DLL Initialization Failed")}, {0xe06d7363, _T("a Microsoft C++ Exception")}, }; for (int i = 0; i < sizeof(ExceptionMap) / sizeof(ExceptionMap[0]); i++) if (ExceptionCode == ExceptionMap[i].ExceptionCode) return ExceptionMap[i].ExceptionName; return _T("an Unknown exception type"); } /// // GetFilePart static TCHAR * GetFilePart(LPCTSTR source) { TCHAR *result = lstrrchr(source, _T('\\')); if (result) result++; else result = (TCHAR *)source; return result; } /// // DumpStack static void DumpStack(HANDLE LogFile, DWORD *pStack) { hprintf(LogFile, _T("\r\n\r\nStack:\r\n")); __try { // Esp contains the bottom of the stack, or at least the bottom of // the currently used area. DWORD* pStackTop; __asm { // Load the top (highest address) of the stack from the // thread information block. It will be found there in // Win9x and Windows NT. mov eax, fs:[4] mov pStackTop, eax } if (pStackTop > pStack + MaxStackDump) pStackTop = pStack + MaxStackDump; int Count = 0; DWORD* pStackStart = pStack; int nDwordsPrinted = 0; while (pStack + 1 <= pStackTop) { if ((Count % StackColumns) == 0) { pStackStart = pStack; nDwordsPrinted = 0; hprintf(LogFile, _T("0x%08x: "), pStack); } if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop) { hprintf(LogFile, _T("%08x "), *pStack); nDwordsPrinted++; int n = nDwordsPrinted; while (n < 4) { hprintf(LogFile, _T(" ")); n++; } for (int i = 0; i < nDwordsPrinted; i++) { DWORD dwStack = *pStackStart; for (int j = 0; j < 4; j++) { char c = (char)(dwStack & 0xFF); if (c < 0x20 || c > 0x7E) c = '.'; #ifdef _UNICODE WCHAR w = (WCHAR)c; hprintf(LogFile, _T("%c"), w); #else hprintf(LogFile, _T("%c"), c); #endif dwStack = dwStack >> 8; } pStackStart++; } hprintf(LogFile, _T("\r\n")); } else { hprintf(LogFile, _T("%08x "), *pStack); nDwordsPrinted++; } pStack++; } hprintf(LogFile, _T("\r\n")); } __except(EXCEPTION_EXECUTE_HANDLER) { hprintf(LogFile, _T("Exception encountered during stack dump.\r\n")); } } /// // DumpRegisters static void DumpRegisters(HANDLE LogFile, PCONTEXT Context) { // Print out the register values in an XP error window compatible format. hprintf(LogFile, _T("\r\n")); hprintf(LogFile, _T("Context:\r\n")); hprintf(LogFile, _T("EDI: 0x%08x ESI: 0x%08x EAX: 0x%08x\r\n"), Context->Edi, Context->Esi, Context->Eax); hprintf(LogFile, _T("EBX: 0x%08x ECX: 0x%08x EDX: 0x%08x\r\n"), Context->Ebx, Context->Ecx, Context->Edx); hprintf(LogFile, _T("EIP: 0x%08x EBP: 0x%08x SegCs: 0x%08x\r\n"), Context->Eip, Context->Ebp, Context->SegCs); hprintf(LogFile, _T("EFlags: 0x%08x ESP: 0x%08x SegSs: 0x%08x\r\n"), Context->EFlags, Context->Esp, Context->SegSs); } /// /// // // RecordExceptionInfo // /// /// int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS pExceptPtrs, LPCTSTR lpszMessage) { static bool bFirstTime = true; if (!bFirstTime) // Going recursive! That must mean this routine crashed! return EXCEPTION_CONTINUE_SEARCH; bFirstTime = false; // Create a filename to record the error information to. // Storing it in the executable directory works well. TCHAR szModuleName[MAX_PATH*2]; ZeroMemory(szModuleName, sizeof(szModuleName)); if (GetModuleFileName(0, szModuleName, _countof(szModuleName)-2) <= 0) lstrcpy(szModuleName, _T("Unknown")); TCHAR *pszFilePart = GetFilePart(szModuleName); // Extract the file name portion and remove it's file extension TCHAR szFileName[MAX_PATH*2]; lstrcpy(szFileName, pszFilePart); TCHAR *lastperiod = lstrrchr(szFileName, _T('.')); if (lastperiod) lastperiod[0] = 0; #ifdef XCRASHREPORT_WRITE_ERROR_LOG // Replace the executable filename with our error log file name lstrcpy(pszFilePart, XCRASHREPORT_ERROR_LOG_FILE); HANDLE hLogFile = CreateFile(szModuleName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, 0); if (hLogFile == INVALID_HANDLE_VALUE) { OutputDebugString(_T("Error creating exception report\r\n")); return EXCEPTION_CONTINUE_SEARCH; } // Append to the error log SetFilePointer(hLogFile, 0, 0, FILE_END); // Print out a blank line to separate this error log from any previous ones //hprintf(hLogFile, _T("\r\n")); PEXCEPTION_RECORD Exception = pExceptPtrs->ExceptionRecord; PCONTEXT Context = pExceptPtrs->ContextRecord; TCHAR szCrashModulePathName[MAX_PATH*2]; ZeroMemory(szCrashModulePathName, sizeof(szCrashModulePathName)); TCHAR *pszCrashModuleFileName = _T("Unknown"); MEMORY_BASIC_INFORMATION MemInfo; // VirtualQuery can be used to get the allocation base associated with a // code address, which is the same as the ModuleHandle. This can be used // to get the filename of the module that the crash happened in. if (VirtualQuery((void*)Context->Eip, &MemInfo, sizeof(MemInfo)) && (GetModuleFileName((HINSTANCE)MemInfo.AllocationBase, szCrashModulePathName, sizeof(szCrashModulePathName)-2) > 0)) { pszCrashModuleFileName = GetFilePart(szCrashModulePathName); } // Print out the beginning of the error log in a Win95 error window // compatible format. hprintf(hLogFile, _T("%s caused %s (0x%08x) \r\nin module %s at %04x:%08x.\r\n\r\n"), szFileName, GetExceptionDescription(Exception->ExceptionCode), Exception->ExceptionCode, pszCrashModuleFileName, Context->SegCs, Context->Eip); hprintf(hLogFile, _T("Exception handler called in %s.\r\n"), lpszMessage); DumpSystemInformation(hLogFile); // If the exception was an access violation, print out some additional // information, to the error log and the debugger. if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION && Exception->NumberParameters >= 2) { TCHAR szDebugMessage[1000]; const TCHAR* readwrite = _T("Read from"); if (Exception->ExceptionInformation[0]) readwrite = _T("Write to"); wsprintf(szDebugMessage, _T("%s location %08x caused an access violation.\r\n"), readwrite, Exception->ExceptionInformation[1]); #ifdef _DEBUG // The Visual C++ debugger doesn't actually tell you whether a read // or a write caused the access violation, nor does it tell what // address was being read or written. So I fixed that. OutputDebugString(_T("Exception handler: ")); OutputDebugString(szDebugMessage); #endif hprintf(hLogFile, _T("%s"), szDebugMessage); } DumpRegisters(hLogFile, Context); // Print out the bytes of code at the instruction pointer. Since the // crash may have been caused by an instruction pointer that was bad, // this code needs to be wrapped in an exception handler, in case there // is no memory to read. If the dereferencing of code[] fails, the // exception handler will print '??'. hprintf(hLogFile, _T("\r\nBytes at CS:EIP:\r\n")); BYTE * code = (BYTE *)Context->Eip; for (int codebyte = 0; codebyte < NumCodeBytes; codebyte++) { __try { hprintf(hLogFile, _T("%02x "), code[codebyte]); } __except(EXCEPTION_EXECUTE_HANDLER) { hprintf(hLogFile, _T("?? ")); } } // Time to print part or all of the stack to the error log. This allows // us to figure out the call stack, parameters, local variables, etc. // Esp contains the bottom of the stack, or at least the bottom of // the currently used area DWORD* pStack = (DWORD *)Context->Esp; DumpStack(hLogFile, pStack); DumpModuleList(hLogFile); hprintf(hLogFile, _T("\r\n===== [end of %s] =====\r\n"), XCRASHREPORT_ERROR_LOG_FILE); hflush(hLogFile); CloseHandle(hLogFile); #endif //XCRASHREPORT_WRITE_ERROR_LOG /// // // write minidump // /// #ifdef XCRASHREPORT_WRITE_MINIDUMP // Replace the filename with our minidump file name lstrcpy(pszFilePart, XCRASHREPORT_MINI_DUMP_FILE); // Create the file HANDLE hMiniDumpFile = CreateFile( szModuleName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); // Write the minidump to the file if (hMiniDumpFile != INVALID_HANDLE_VALUE) { DumpMiniDump(hMiniDumpFile, pExceptPtrs); // Close file CloseHandle(hMiniDumpFile); } #endif // XCRASHREPORT_WRITE_MINIDUMP if (IsDebuggerPresent()) { // let the debugger catch this - // return the magic value which tells Win32 that this handler didn't // actually handle the exception - so that things will proceed as per // normal. return EXCEPTION_CONTINUE_SEARCH; } else { /// // // pop up our crash report app // /// // Replace the filename with our crash report exe file name lstrcpy(pszFilePart, XCRASHREPORT_CRASH_REPORT_APP); TCHAR szCommandLine[MAX_PATH]; lstrcpy(szCommandLine, szModuleName); lstrcat(szCommandLine, _T(" \"")); // surround app name with quotes ZeroMemory(szModuleName, sizeof(szModuleName)); GetModuleFileName(0, szModuleName, _countof(szModuleName)-2); lstrcat(szCommandLine, GetFilePart(szModuleName)); lstrcat(szCommandLine, _T("\"")); //MessageBox(NULL,szCommandLine,L"",MB_OK); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); if (CreateProcess( NULL, // name of executable module szCommandLine, // command line string NULL, // process attributes NULL, // thread attributes FALSE, // handle inheritance option 0, // creation flags NULL, // new environment block NULL, // current directory name &si, // startup information &pi)) // process information { // XCrashReport.exe was successfully started, so // suppress the standard crash dialog return EXCEPTION_EXECUTE_HANDLER; } else { // XCrashReport.exe was not started - let // the standard crash dialog appear return EXCEPTION_CONTINUE_SEARCH; } } }
GetWinVer.h
#ifndef GETWINVER_H #define GETWINVER_H #define WUNKNOWNSTR _T("unknown Windows version") #define W95STR _T("Windows 95") #define W95SP1STR _T("Windows 95 SP1") #define W95OSR2STR _T("Windows 95 OSR2") #define W98STR _T("Windows 98") #define W98SP1STR _T("Windows 98 SP1") #define W98SESTR _T("Windows 98 SE") #define WMESTR _T("Windows ME") #define WNT351STR _T("Windows NT 3.51") #define WNT4STR _T("Windows NT 4") #define W2KSTR _T("Windows 2000") #define WXPSTR _T("Windows XP") #define W2003SERVERSTR _T("Windows 2003 Server") #define WCESTR _T("Windows CE") #define WUNKNOWN 0 #define W9XFIRST 1 #define W95 1 #define W95SP1 2 #define W95OSR2 3 #define W98 4 #define W98SP1 5 #define W98SE 6 #define WME 7 #define W9XLAST 99 #define WNTFIRST 101 #define WNT351 101 #define WNT4 102 #define W2K 103 #define WXP 104 #define W2003SERVER 105 #define WNTLAST 199 #define WCEFIRST 201 #define WCE 201 #define WCELAST 299 BOOL GetWinVer(LPTSTR pszVersion, int *nVersion, LPTSTR pszMajorMinorBuild); #endif //GETWINVER_H
GetWinVer.cpp
#include "stdafx.h" #include "tchar.h" #include "GetWinVer.h" #pragma warning(disable : 4996) // from winbase.h #ifndef VER_PLATFORM_WIN32s #define VER_PLATFORM_WIN32s 0 #endif #ifndef VER_PLATFORM_WIN32_WINDOWS #define VER_PLATFORM_WIN32_WINDOWS 1 #endif #ifndef VER_PLATFORM_WIN32_NT #define VER_PLATFORM_WIN32_NT 2 #endif #ifndef VER_PLATFORM_WIN32_CE #define VER_PLATFORM_WIN32_CE 3 #endif // GetWinVer BOOL GetWinVer(LPTSTR pszVersion, int *nVersion, LPTSTR pszMajorMinorBuild) { if (!pszVersion || !nVersion || !pszMajorMinorBuild) return FALSE; lstrcpy(pszVersion, WUNKNOWNSTR); *nVersion = WUNKNOWN; OSVERSIONINFO osinfo; osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osinfo)) return FALSE; DWORD dwPlatformId = osinfo.dwPlatformId; DWORD dwMinorVersion = osinfo.dwMinorVersion; DWORD dwMajorVersion = osinfo.dwMajorVersion; DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this wsprintf(pszMajorMinorBuild, _T("%u.%u.%u"), dwMajorVersion, dwMinorVersion, dwBuildNumber); if ((dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (dwMajorVersion == 4)) { if ((dwMinorVersion < 10) && (dwBuildNumber == 950)) { lstrcpy(pszVersion, W95STR); *nVersion = W95; } else if ((dwMinorVersion < 10) && ((dwBuildNumber > 950) && (dwBuildNumber <= 1080))) { lstrcpy(pszVersion, W95SP1STR); *nVersion = W95SP1; } else if ((dwMinorVersion < 10) && (dwBuildNumber > 1080)) { lstrcpy(pszVersion, W95OSR2STR); *nVersion = W95OSR2; } else if ((dwMinorVersion == 10) && (dwBuildNumber == 1998)) { lstrcpy(pszVersion, W98STR); *nVersion = W98; } else if ((dwMinorVersion == 10) && ((dwBuildNumber > 1998) && (dwBuildNumber < 2183))) { lstrcpy(pszVersion, W98SP1STR); *nVersion = W98SP1; } else if ((dwMinorVersion == 10) && (dwBuildNumber >= 2183)) { lstrcpy(pszVersion, W98SESTR); *nVersion = W98SE; } else if (dwMinorVersion == 90) { lstrcpy(pszVersion, WMESTR); *nVersion = WME; } } else if (dwPlatformId == VER_PLATFORM_WIN32_NT) { if ((dwMajorVersion == 3) && (dwMinorVersion == 51)) { lstrcpy(pszVersion, WNT351STR); *nVersion = WNT351; } else if ((dwMajorVersion == 4) && (dwMinorVersion == 0)) { lstrcpy(pszVersion, WNT4STR); *nVersion = WNT4; } else if ((dwMajorVersion == 5) && (dwMinorVersion == 0)) { lstrcpy(pszVersion, W2KSTR); *nVersion = W2K; } else if ((dwMajorVersion == 5) && (dwMinorVersion == 1)) { lstrcpy(pszVersion, WXPSTR); *nVersion = WXP; } else if ((dwMajorVersion == 5) && (dwMinorVersion == 2)) { lstrcpy(pszVersion, W2003SERVERSTR); *nVersion = W2003SERVER; } } else if (dwPlatformId == VER_PLATFORM_WIN32_CE) { lstrcpy(pszVersion, WCESTR); *nVersion = WCE; } return TRUE; }
MiniVersion.h
#ifndef MINIVERSION_H #define MINIVERSION_H class CMiniVersion { // constructors public: CMiniVersion(LPCTSTR lpszPath = NULL); BOOL Init(); void Release(); // operations public: // attributes public: // fixed info BOOL GetFileVersion(WORD *pwVersion); BOOL GetProductVersion(WORD* pwVersion); BOOL GetFileFlags(DWORD& rdwFlags); BOOL GetFileOS(DWORD& rdwOS); BOOL GetFileType(DWORD& rdwType); BOOL GetFileSubtype(DWORD& rdwType); // string info BOOL GetCompanyName(LPTSTR lpszCompanyName, int nSize); BOOL GetFileDescription(LPTSTR lpszFileDescription, int nSize); BOOL GetProductName(LPTSTR lpszProductName, int nSize); // implementation protected: BOOL GetFixedInfo(VS_FIXEDFILEINFO& rFixedInfo); BOOL GetStringInfo(LPCTSTR lpszKey, LPTSTR lpszValue); BYTE* m_pData; DWORD m_dwHandle; WORD m_wFileVersion[4]; WORD m_wProductVersion[4]; DWORD m_dwFileFlags; DWORD m_dwFileOS; DWORD m_dwFileType; DWORD m_dwFileSubtype; TCHAR m_szPath[MAX_PATH*2]; TCHAR m_szCompanyName[MAX_PATH*2]; TCHAR m_szProductName[MAX_PATH*2]; TCHAR m_szFileDescription[MAX_PATH*2]; }; #endif
MiniVersion.cpp
#include "stdafx.h" #include "MiniVersion.h" #pragma message("automatic link to VERSION.LIB") #pragma comment(lib, "version.lib") /// // ctor CMiniVersion::CMiniVersion(LPCTSTR lpszPath) { ZeroMemory(m_szPath, sizeof(m_szPath)); if (lpszPath && lpszPath[0] != 0) { lstrcpyn(m_szPath, lpszPath, sizeof(m_szPath)-1); } else { } m_pData = NULL; m_dwHandle = 0; for (int i = 0; i < 4; i++) { m_wFileVersion[i] = 0; m_wProductVersion[i] = 0; } m_dwFileFlags = 0; m_dwFileOS = 0; m_dwFileType = 0; m_dwFileSubtype = 0; ZeroMemory(m_szCompanyName, sizeof(m_szCompanyName)); ZeroMemory(m_szProductName, sizeof(m_szProductName)); ZeroMemory(m_szFileDescription, sizeof(m_szFileDescription)); Init(); } /// // Init BOOL CMiniVersion::Init() { DWORD dwHandle; DWORD dwSize; BOOL rc; dwSize = ::GetFileVersionInfoSize(m_szPath, &dwHandle); if (dwSize == 0) return FALSE; m_pData = new BYTE [dwSize + 1]; ZeroMemory(m_pData, dwSize+1); rc = ::GetFileVersionInfo(m_szPath, dwHandle, dwSize, m_pData); if (!rc) return FALSE; // get fixed info VS_FIXEDFILEINFO FixedInfo; if (GetFixedInfo(FixedInfo)) { m_wFileVersion[0] = HIWORD(FixedInfo.dwFileVersionMS); m_wFileVersion[1] = LOWORD(FixedInfo.dwFileVersionMS); m_wFileVersion[2] = HIWORD(FixedInfo.dwFileVersionLS); m_wFileVersion[3] = LOWORD(FixedInfo.dwFileVersionLS); m_wProductVersion[0] = HIWORD(FixedInfo.dwProductVersionMS); m_wProductVersion[1] = LOWORD(FixedInfo.dwProductVersionMS); m_wProductVersion[2] = HIWORD(FixedInfo.dwProductVersionLS); m_wProductVersion[3] = LOWORD(FixedInfo.dwProductVersionLS); m_dwFileFlags = FixedInfo.dwFileFlags; m_dwFileOS = FixedInfo.dwFileOS; m_dwFileType = FixedInfo.dwFileType; m_dwFileSubtype = FixedInfo.dwFileSubtype; } else return FALSE; // get string info GetStringInfo(_T("CompanyName"), m_szCompanyName); GetStringInfo(_T("FileDescription"), m_szFileDescription); GetStringInfo(_T("ProductName"), m_szProductName); return TRUE; } /// // Release void CMiniVersion::Release() { // do this manually, because we can't use objects requiring // a dtor within an exception handler if (m_pData) delete [] m_pData; m_pData = NULL; } /// // GetFileVersion BOOL CMiniVersion::GetFileVersion(WORD * pwVersion) { for (int i = 0; i < 4; i++) *pwVersion++ = m_wFileVersion[i]; return TRUE; } /// // GetProductVersion BOOL CMiniVersion::GetProductVersion(WORD * pwVersion) { for (int i = 0; i < 4; i++) *pwVersion++ = m_wProductVersion[i]; return TRUE; } /// // GetFileFlags BOOL CMiniVersion::GetFileFlags(DWORD& rdwFlags) { rdwFlags = m_dwFileFlags; return TRUE; } /// // GetFileOS BOOL CMiniVersion::GetFileOS(DWORD& rdwOS) { rdwOS = m_dwFileOS; return TRUE; } /// // GetFileType BOOL CMiniVersion::GetFileType(DWORD& rdwType) { rdwType = m_dwFileType; return TRUE; } /// // GetFileSubtype BOOL CMiniVersion::GetFileSubtype(DWORD& rdwType) { rdwType = m_dwFileSubtype; return TRUE; } /// // GetCompanyName BOOL CMiniVersion::GetCompanyName(LPTSTR lpszCompanyName, int nSize) { if (!lpszCompanyName) return FALSE; ZeroMemory(lpszCompanyName, nSize); lstrcpyn(lpszCompanyName, m_szCompanyName, nSize-1); return TRUE; } /// // GetFileDescription BOOL CMiniVersion::GetFileDescription(LPTSTR lpszFileDescription, int nSize) { if (!lpszFileDescription) return FALSE; ZeroMemory(lpszFileDescription, nSize); lstrcpyn(lpszFileDescription, m_szFileDescription, nSize-1); return TRUE; } /// // GetProductName BOOL CMiniVersion::GetProductName(LPTSTR lpszProductName, int nSize) { if (!lpszProductName) return FALSE; ZeroMemory(lpszProductName, nSize); lstrcpyn(lpszProductName, m_szProductName, nSize-1); return TRUE; } /// /// // // protected methods // /// /// /// // GetFixedInfo BOOL CMiniVersion::GetFixedInfo(VS_FIXEDFILEINFO& rFixedInfo) { BOOL rc; UINT nLength; VS_FIXEDFILEINFO *pFixedInfo = NULL; if (!m_pData) return FALSE; if (m_pData) rc = ::VerQueryValue(m_pData, _T("\\"), (void **) &pFixedInfo, &nLength); else rc = FALSE; if (rc) memcpy (&rFixedInfo, pFixedInfo, sizeof (VS_FIXEDFILEINFO)); return rc; } /// // GetStringInfo BOOL CMiniVersion::GetStringInfo(LPCTSTR lpszKey, LPTSTR lpszReturnValue) { BOOL rc; DWORD *pdwTranslation; UINT nLength; LPTSTR lpszValue; if (m_pData == NULL) return FALSE; if (!lpszReturnValue) return FALSE; if (!lpszKey) return FALSE; *lpszReturnValue = 0; rc = ::VerQueryValue(m_pData, _T("\\VarFileInfo\\Translation"), (void**) &pdwTranslation, &nLength); if (!rc) return FALSE; TCHAR szKey[2000]; wsprintf(szKey, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD (*pdwTranslation), HIWORD (*pdwTranslation), lpszKey); rc = ::VerQueryValue(m_pData, szKey, (void**) &lpszValue, &nLength); if (!rc) return FALSE; lstrcpy(lpszReturnValue, lpszValue); return TRUE; }
第二步:在main函数处加入try catch 捕获异常
// Duilib_Login.cpp : 定义应用程序的入口点。 // #include "CefBrowserApp.h" #include "MainFrameWnd.h" #include "ExceptionHandler.h" //#define CEF_USE_SANDBOX 560 int Mymain(HINSTANCE hInstance) { CPaintManagerUI::SetInstance(hInstance); CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()); HRESULT Hr = ::CoInitialize(NULL); if (FAILED(Hr)) return 0; /***************************************begin初始化cef*******************************************/ void* sandbox_info = NULL; #if defined(CEF_USE_SANDBOX) CefScopedSandboxInfo scoped_sandbox; sandbox_info = scoped_sandbox.sandbox_info(); #endif CefMainArgs main_args(hInstance); CefRefPtr<CCefBrowserApp> spApp(new CCefBrowserApp); // Execute the secondary process, if any. int exit_code = CefExecuteProcess(main_args, spApp.get(), sandbox_info); if (exit_code >= 0) return exit_code; CefRefPtr<CefCommandLine> command_line; command_line = CefCommandLine::CreateCommandLine(); command_line->AppendSwitch("no-proxy-server");//加载慢,关闭代理试试 //command_line->AppendSwitch("--disable-web-security");//关闭同源策略 //command_line->AppendSwitchWithValue("ppapi-flash-version", "28.0.0.137");//PepperFlash\manifest.json中的version //command_line->AppendSwitchWithValue("ppapi-flash-path", "PepperFlash\\pepflashplayer.dll"); CefSettings cSettings; const char* loc = "zh-CN"; cSettings.no_sandbox = true; cSettings.multi_threaded_message_loop = true; //cSettings.single_process = false; cSettings.log_severity = LOGSEVERITY_DISABLE;//设置日志级别,解决安装启动佰卓数安后桌面出现一个debug.log文件(调试阶段可以去掉) CefString(&cSettings.locale).FromASCII(loc); cef_string_from_ascii(loc, strlen(loc), &cSettings.locale); // Execute the secondary process, if any. CefInitialize(main_args, cSettings, spApp.get(), sandbox_info); /***************************************结束初始化cef*******************************************/ CMainFrameWnd Main; Main.Create(NULL, _T("MainFrameWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES); Main.CenterWindow(); Main.ShowModal(); //if (!cSettings.multi_threaded_message_loop) { // // Run the CEF message loop. This function will block until the application // // recieves a WM_QUIT message. // CefRunMessageLoop(); //} //else { // DuiLib::CPaintManagerUI::MessageLoop(); //} //CefShutdown(); ::CoUninitialize(); return 0; } int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow) { __try { Mymain(hInstance); } __except (RecordExceptionInfo(GetExceptionInformation(), _T("DuilibDemo.cpp - _tWinMain"))) { // Do nothing here - RecordExceptionInfo() has already done // everything that is needed. Actually this code won't even // get called unless you return EXCEPTION_EXECUTE_HANDLER from // the __except clause. } return 0; }
手动让程序崩溃:
*(int*)0 = 5;
BugReport源码:点击下载