一份生成windows转储文件的源代码

564 阅读2分钟

抄袭

正文

抄袭某网友的

  • helper.h
    #pragma once
    #include <tchar.h>
    #include <Windows.h>
    #include <DbgHelp.h>
    
    #pragma comment(lib, "user32.lib")
    
    int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers)
    {
            // 定义函数指针
            typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
                    HANDLE,
                    DWORD,
                    HANDLE,
                    MINIDUMP_TYPE,
                    PMINIDUMP_EXCEPTION_INFORMATION,
                    PMINIDUMP_USER_STREAM_INFORMATION,
                    PMINIDUMP_CALLBACK_INFORMATION
                    );
            // 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
            MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
        HMODULE hDbgHelp = LoadLibrary(_T("DbgHelp.dll"));
            if (NULL == hDbgHelp)
            {
                    return EXCEPTION_CONTINUE_EXECUTION;
            }
            pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
    
            if (NULL == pfnMiniDumpWriteDump)
            {
                    FreeLibrary(hDbgHelp);
                    return EXCEPTION_CONTINUE_EXECUTION;
            }
            // 创建 dmp 文件件
            TCHAR szFileName[MAX_PATH] = { 0 };
        TCHAR szVersion[] = L"DumpFile";
            SYSTEMTIME stLocalTime;
            GetLocalTime(&stLocalTime);
            wsprintf(szFileName, L"%s-%04d%02d%02d-%02d%02d%02d.dmp",
                    szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
                    stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
            HANDLE hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
                    FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
            if (INVALID_HANDLE_VALUE == hDumpFile)
            {
                    FreeLibrary(hDbgHelp);
                    return EXCEPTION_CONTINUE_EXECUTION;
            }
            // 写入 dmp 文件
            MINIDUMP_EXCEPTION_INFORMATION expParam;
            expParam.ThreadId = GetCurrentThreadId();
            expParam.ExceptionPointers = pExceptionPointers;
            expParam.ClientPointers = FALSE;
            pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
                    hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
            // 释放文件
            CloseHandle(hDumpFile);
            FreeLibrary(hDbgHelp);
            return EXCEPTION_EXECUTE_HANDLER;
    }
    
    LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
    {
            // 这里做一些异常的过滤或提示
        if (IsDebuggerPresent()) {
                    return EXCEPTION_CONTINUE_SEARCH;
            }
            return GenerateMiniDump(lpExceptionInfo);
    }
    
  • 使用
    SetUnhandledExceptionFilter(ExceptionFilter);
    

亲测,这个直接在.pro工程里能直接编译过

  • minidump.h
    #pragma once  
    #include <windows.h>  
    #include <DbgHelp.h>  
    #include <stdlib.h>  
    
    
    #pragma comment(lib, "dbghelp.lib")
    // 自己添加的,否则链接找不到函数符号(库函数里的)
    #pragma comment(lib, "user32.lib")
    
    // 自己注释的,才能适应x64的工程
    // #ifndef _M_IX86
    // #error "The following code only works for x86!"
    // #endif
    
    inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName)
    {
        if (pModuleName == 0)
        {
            return FALSE;
        }
    
        WCHAR szFileName[_MAX_FNAME] = L"";
        _wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
    
        if (_wcsicmp(szFileName, L"ntdll") == 0)
            return TRUE;
    
        return FALSE;
    }
    
    inline BOOL CALLBACK MiniDumpCallback(PVOID                            pParam,
        const PMINIDUMP_CALLBACK_INPUT   pInput,
        PMINIDUMP_CALLBACK_OUTPUT        pOutput)
    {
        if (pInput == 0 || pOutput == 0)
            return FALSE;
    
        switch (pInput->CallbackType)
        {
        case ModuleCallback:
            if (pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
                if (!IsDataSectionNeeded(pInput->Module.FullPath))
                    pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
        case IncludeModuleCallback:
        case IncludeThreadCallback:
        case ThreadCallback:
        case ThreadExCallback:
            return TRUE;
        default:;
        }
    
        return FALSE;
    }
    
    inline void CreateMiniDump(PEXCEPTION_POINTERS pep, LPCTSTR strFileName)
    {
        HANDLE hFile = CreateFile(strFileName, GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    
        if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
        {
            MINIDUMP_EXCEPTION_INFORMATION mdei;
            mdei.ThreadId = GetCurrentThreadId();
            mdei.ExceptionPointers = pep;
            mdei.ClientPointers = NULL;
    
            MINIDUMP_CALLBACK_INFORMATION mci;
            mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MiniDumpCallback;
            mci.CallbackParam = 0;
    
            ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hFile, MiniDumpNormal, (pep != 0) ? &mdei : 0, NULL, &mci);
    
            CloseHandle(hFile);
        }
    }
    
    LONG __stdcall MyUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
    {
        CreateMiniDump(pExceptionInfo, L"core.dmp");
        MessageBox(0, L"Error", L"error", MB_OK);
        /*printf("Error   address   %x/n", pExceptionInfo->ExceptionRecord->ExceptionAddress);
        printf("CPU   register:/n");
        printf("eax   %x   ebx   %x   ecx   %x   edx   %x/n", pExceptionInfo->ContextRecord->Eax,
            pExceptionInfo->ContextRecord->Ebx, pExceptionInfo->ContextRecord->Ecx,
            pExceptionInfo->ContextRecord->Edx);*/
        return   EXCEPTION_EXECUTE_HANDLER;
    }
    
    // 此函数一旦成功调用,之后对 SetUnhandledExceptionFilter 的调用将无效  
    void DisableSetUnhandledExceptionFilter()
    {
        void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"),
            "SetUnhandledExceptionFilter");
    
        if (addr)
        {
            unsigned char code[16];
            int size = 0;
    
            code[size++] = 0x33;
            code[size++] = 0xC0;
            code[size++] = 0xC2;
            code[size++] = 0x04;
            code[size++] = 0x00;
    
            DWORD dwOldFlag, dwTempFlag;
            VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
            WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
            VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
        }
    }
    
    void InitMinDump()
    {
        //注册异常处理函数  
        SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
    
        //使SetUnhandledExceptionFilter  
        DisableSetUnhandledExceptionFilter();
    }
    
  • Qt生成 .pdb文件
    QMAKE_LFLAGS_RELEASE    += /MAP
    QMAKE_CFLAGS_RELEASE    += /Zi
    QMAKE_LFLAGS_RELEASE    += /debug /opt:ref
    
  • 使用
    #include "minidump.h"
    // regist dump genereator
    SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);