zoukankan      html  css  js  c++  java
  • 给自己的程序添加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_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
    "));
                RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
            } 
            __except(DumpMiniDump(hFile, GetExceptionInformation()),
                     EXCEPTION_CONTINUE_EXECUTION) 
            {
            }
        } 
        else
        {
            OutputDebugString(_T("writing minidump
    "));
            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('');
        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('');
                
                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
    "), nModuleNo);
                hprintf(LogFile, _T("%s
    "), szModName);
                hprintf(LogFile, _T("Image Base: 0x%08x  Image Size: 0x%08x
    "), 
                    NTHeader->OptionalHeader.ImageBase, 
                    NTHeader->OptionalHeader.SizeOfImage), 
    
                hprintf(LogFile, _T("Checksum:   0x%08x  Time Stamp: 0x%08x
    "), 
                    NTHeader->OptionalHeader.CheckSum,
                    NTHeader->FileHeader.TimeDateStamp);
    
                hprintf(LogFile, _T("File Size:  %-10d  File Time:  %s
    "),
                            FileSize, TimeBuffer);
    
                hprintf(LogFile, _T("Version Information:
    "));
    
                CMiniVersion ver(szModName);
                TCHAR szBuf[200];
                WORD dwBuf[4];
    
                ver.GetCompanyName(szBuf, sizeof(szBuf)-1);
                hprintf(LogFile, _T("   Company:    %s
    "), szBuf);
    
                ver.GetProductName(szBuf, sizeof(szBuf)-1);
                hprintf(LogFile, _T("   Product:    %s
    "), szBuf);
    
                ver.GetFileDescription(szBuf, sizeof(szBuf)-1);
                hprintf(LogFile, _T("   FileDesc:   %s
    "), szBuf);
    
                ver.GetFileVersion(dwBuf);
                hprintf(LogFile, _T("   FileVer:    %d.%d.%d.%d
    "), 
                    dwBuf[0], dwBuf[1], dwBuf[2], dwBuf[3]);
    
                ver.GetProductVersion(dwBuf);
                hprintf(LogFile, _T("   ProdVer:    %d.%d.%d.%d
    "), 
                    dwBuf[0], dwBuf[1], dwBuf[2], dwBuf[3]);
    
                ver.Release();
    
                hprintf(LogFile, _T("
    "));
    
                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.
    "), 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.
    "), szModuleName, szUserName);
    
        // print out operating system
        TCHAR szWinVer[50], szMajorMinorBuild[50];
        int nWinVer;
        GetWinVer(szWinVer, &nWinVer, szMajorMinorBuild);
        hprintf(LogFile, _T("Operating system:  %s (%s).
    "), 
            szWinVer, szMajorMinorBuild);
    
        SYSTEM_INFO    SystemInfo;
        GetSystemInfo(&SystemInfo);
        hprintf(LogFile, _T("%d processor(s), type %d.
    "),
                    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.
    "), MemInfo.dwMemoryLoad);
        hprintf(LogFile, _T("%d MBytes physical memory.
    "), (MemInfo.dwTotalPhys +
                    ONEM - 1) / ONEM);
        hprintf(LogFile, _T("%d MBytes physical memory free.
    "), 
            (MemInfo.dwAvailPhys + ONEM - 1) / ONEM);
        hprintf(LogFile, _T("%d MBytes paging file.
    "), (MemInfo.dwTotalPageFile +
                    ONEM - 1) / ONEM);
        hprintf(LogFile, _T("%d MBytes paging file free.
    "), 
            (MemInfo.dwAvailPageFile + ONEM - 1) / ONEM);
        hprintf(LogFile, _T("%d MBytes user address space.
    "), 
            (MemInfo.dwTotalVirtual + ONEM - 1) / ONEM);
        hprintf(LogFile, _T("%d MBytes user address space free.
    "), 
            (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("
    
    Stack:
    "));
    
        __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("
    "));
                }
                else
                {
                    hprintf(LogFile, _T("%08x "), *pStack);
                    nDwordsPrinted++;
                }
                pStack++;
            }
            hprintf(LogFile, _T("
    "));
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            hprintf(LogFile, _T("Exception encountered during stack dump.
    "));
        }
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    // DumpRegisters
    static void DumpRegisters(HANDLE LogFile, PCONTEXT Context)
    {
        // Print out the register values in an XP error window compatible format.
        hprintf(LogFile, _T("
    "));
        hprintf(LogFile, _T("Context:
    "));
        hprintf(LogFile, _T("EDI:    0x%08x  ESI: 0x%08x  EAX:   0x%08x
    "),
                    Context->Edi, Context->Esi, Context->Eax);
        hprintf(LogFile, _T("EBX:    0x%08x  ECX: 0x%08x  EDX:   0x%08x
    "),
                    Context->Ebx, Context->Ecx, Context->Edx);
        hprintf(LogFile, _T("EIP:    0x%08x  EBP: 0x%08x  SegCs: 0x%08x
    "),
                    Context->Eip, Context->Ebp, Context->SegCs);
        hprintf(LogFile, _T("EFlags: 0x%08x  ESP: 0x%08x  SegSs: 0x%08x
    "),
                    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
    "));
            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("
    "));
    
        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) 
    in module %s at %04x:%08x.
    
    "),
                    szFileName, GetExceptionDescription(Exception->ExceptionCode),
                    Exception->ExceptionCode,
                    pszCrashModuleFileName, Context->SegCs, Context->Eip);
    
        hprintf(hLogFile, _T("Exception handler called in %s.
    "), 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.
    "),
                        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("
    Bytes at CS:EIP:
    "));
        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("
    ===== [end of %s] =====
    "), 
            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");//PepperFlashmanifest.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源码:点击下载

  • 相关阅读:
    ansible设置串行的方法
    给k8s集群中的node节点加标签
    Prometheus断电后启动异常 Error on ingesting samples
    配置 containerd 镜像仓库完全攻略
    这款网络排查工具,堪称神器!
    k8s备份工具之velero
    CentOS 7安装megacli
    Atitit .h5文件上传 v3
    php切片处理视频大文件思路
    php切片处理视频大文件功能
  • 原文地址:https://www.cnblogs.com/chechen/p/10123923.html
Copyright © 2011-2022 走看看