给自己的程序添加BugReport
转载: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_Htypedef 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])) #endifconst 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 sizeHANDLE 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 intsconst 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 memorypageNum += 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 modulesLastAllocationBase = MemInfo.AllocationBase;if (DumpModuleInfo(LogFile, (HINSTANCE)LastAllocationBase, nModuleNo)){nModuleNo++;}}}elsepageNum += SIXTYFOURK / PageSize;}elsepageNum += 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 systemTCHAR 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) #endifExceptionNames 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++;elseresult = (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 _UNICODEWCHAR w = (WCHAR)c;hprintf(LogFile, _T("%c"), w); #elsehprintf(LogFile, _T("%c"), c); #endifdwStack = 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 extensionTCHAR 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 logSetFilePointer(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); #endifhprintf(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 areaDWORD* 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 fileHANDLE hMiniDumpFile = CreateFile(szModuleName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,NULL);// Write the minidump to the fileif (hMiniDumpFile != INVALID_HANDLE_VALUE){DumpMiniDump(hMiniDumpFile, pExceptPtrs);// Close file CloseHandle(hMiniDumpFile);}#endif // XCRASHREPORT_WRITE_MINIDUMPif (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 quotesZeroMemory(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 moduleszCommandLine, // command line stringNULL, // process attributesNULL, // thread attributesFALSE, // handle inheritance option0, // creation flagsNULL, // new environment blockNULL, // current directory name&si, // startup information&pi)) // process information {// XCrashReport.exe was successfully started, so// suppress the standard crash dialogreturn EXCEPTION_EXECUTE_HANDLER;}else{// XCrashReport.exe was not started - let// the standard crash dialog appearreturn 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 299BOOL 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_Hclass CMiniVersion { // constructors public:CMiniVersion(LPCTSTR lpszPath = NULL);BOOL Init();void Release();// operations public:// attributes public:// fixed infoBOOL GetFileVersion(WORD *pwVersion);BOOL GetProductVersion(WORD* pwVersion);BOOL GetFileFlags(DWORD& rdwFlags);BOOL GetFileOS(DWORD& rdwOS);BOOL GetFileType(DWORD& rdwType);BOOL GetFileSubtype(DWORD& rdwType); // string infoBOOL 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;}elsereturn 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 handlerif (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);elserc = 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 560int 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(); #endifCefMainArgs 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源码:点击下载
给自己的程序添加BugReport相关推荐
- linux下 为自己编写的程序 添加tab自动补全 功能
linux下 为自己编写的程序 添加tab自动补全功能 入门 complete 在我的tmp下随便写了一个a.sh, 为他补全 edit /etc/bash_completion.d/foo _foo ...
- firebase 推送_如何使用Firebase向Web应用程序添加推送通知?
firebase 推送 by Leonardo Cardoso 由莱昂纳多·卡多佐(Leonardo Cardoso) 如何使用Firebase向Web应用程序添加推送通知? (How to add ...
- 为.NET部署应用程序添加个卸载程序
地球人都知道.NET自带的部署程序用起来很方便很简单,但.NET部署程序是没有卸载文件. 下面的方法可以很简单的为你的程序添加1个卸载文件,.NET是利用windows Installer来部署程序的 ...
- 关于把程序添加到打开方式的解决办法
对于如果想用其他某个程序打开某种文件,找到程序在点击确定之后,回到打开方式对话框中,里面没有你刚才选择的程序,无法将你要的程序添加到打开方式里面,只能自己单独×××该程序,在程序里面再打开你要用的文件 ...
- 给你的Flex程序添加深链接和分析-其实比你想象的要简单
Adobe Flash Builder 4 简体中文正式版 Windows版点击下载:http://g.csdn.net/5134151 Adobe Flash Builder 4 简体中文正式版 M ...
- 【OpenGL】二十四、OpenGL 纹理贴图 ( 读取文件内容 | 桌面程序添加控制台窗口 | ‘fopen‘: This function may be unsafe 错误处理 )
文章目录 一.文件读取 二.报错处理 ( 'fopen': This function or variable may be unsafe. ) 三.桌面程序添加控制台窗口 四.相关资源 一.文件读取 ...
- 为ios 应用程序添加图标和添加名字
为应用程序添加图标方法: 1.找到ios工程文件对应的 ***.plist文件.查看是否有 iconfile 或者iconfiles 键值,如果有,请看下一步.如果没有,则随便选中一个键值,然后点击 ...
- qt修改程序图标名称_解决Qt应用程序添加icon图标,修改窗口图标以及添加系统托盘问题...
一.Qt应用程序添加icon图标的方法: 首先,我们需要先准备两个文件,一个是icon图标,另一个是rc文件,我分别命名为"myApp.rc"和"soft.ico&quo ...
- 微信小程序——添加按钮格式
微信小程序--添加按钮 步骤一:在wxml文件中添加按钮代码(图后提供可复制代码) <button class = "button_cat">炸炸呼呼</butt ...
最新文章
- Python 列表、字典、元组的一些小技巧
- Linux下如何执行Shell脚本
- 微型计算机中的外存储器 现在普遍采用,2010澳门特别行政区全国计算机等级考试二级笔试试卷VB最新考试试题库(完整版)...
- linux下C code block环境,linux 使用 codeblocks
- 云计算机教室怎么布线,云和县实验小学计算机教室综合布线及计算机安装预算方案.doc...
- 去贵阳参观大数据到哪参观_您必须参观的四个世界
- 【转】1.B(译).NET4.X并行任务Task需要释放吗?
- 关于数据库中的锁,你不知道的是...
- c++引用另一个类的方法_利用CVE20191132:Windows内核中的另一个NULL指针取消引用...
- 基于Bmob从零开始写一个博客小程序
- Linux上 MongoDB 实现远程连接并设置账号密码
- JavaWeb——jsp原理
- ExtJS 在grid中想要取消checkbox选中的方法
- 设计模式学习(四)工厂模式
- 解决centos 7 打开php文件直接下载问题
- android屏幕大小字体大小,Android字体大小自适应不同分辨率的解决办法
- 解析域名,获得公网地址
- 现在的学生能把老师活活气死
- win10输入法不能切换_怎么解决win10系统微软输入法打不出汉字
- 详解HTML的相对路径写法
热门文章
- Centos-6.7下_Oracle 11gR2静默详细安装过程及排错
- imuxsock lost 353 messages from pid 20261 due to rate-limiting 解决办法
- PostgreSql 功能和操作
- 使用Response.Redirect 两种方法打开一个新窗口
- 如何设置VSS源代码管理工具使用KDiff3
- 服务器中使用Com组建处理Excel 常见问题
- iframe解决跨域ajax请求的方法
- 使用扩展的 CodeIgniter 框架实现 RESTful 框架
- maven详解之生命周期与插件
- 【原创+整理】简述何为调用约定,函数导出名以及extern C