win32通过代码获取dump文件

/ win32+MFC / 没有评论 / 435浏览
/*
** Copyright (C) QPSOFT.COM All rights reserved.
*/

#ifndef INCLUDE_MINIDUMPER_H_
#define INCLUDE_MINIDUMPER_H_

#ifdef _MSC_VER

#include <string>

#include <windows.h>
#include <tchar.h>
#pragma comment(lib, "dbghelp.lib")

#include <dbghelp.h>
#pragma comment(lib, "user32.lib")

#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

namespace Dbg
{

typedef std::string StringA;
typedef std::wstring StringW;

#ifdef _UNICODE
typedef StringW String;
#else
typedef StringA String;
#endif // _UNICODE

typedef BOOL (WINAPI* PFNWRITEDUMP)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_EXCEPTION_INFORMATION,
                                    PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION);

class MiniDumper
{
protected:
    MiniDumper() { ::SetUnhandledExceptionFilter(&MiniDumper::TopLevelExceptionFilter); }
    ~MiniDumper() {};

private:
    MiniDumper(const MiniDumper&);
    const MiniDumper& operator=(const MiniDumper&);

public:
    static MiniDumper* Get()
    {
        static MiniDumper dumper;
        return &dumper;
    }

    void Init(const String& dumpFilePath = String(), const String& appVersion = _T("1.0.0.0"))
    {
        if (!dumpFilePath.empty() && ::PathIsDirectory(dumpFilePath.c_str()))
            m_DumpFilePath = dumpFilePath;
        else
        {
            TCHAR appPath[MAX_PATH];
            ::GetModuleFileName(NULL, appPath, MAX_PATH);
            ::PathRemoveFileSpec(appPath);
            m_DumpFilePath = appPath;
        }

        m_AppVersion = appVersion;
    }

    String GetDumpFile() const
    {
        SYSTEMTIME st;
        ::GetLocalTime(&st);
        TCHAR dt[11];
        wsprintf(dt, _T("%02d%02d%02d%02d%02d"), st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);

        TCHAR appPath[MAX_PATH];
        ::GetModuleFileName(NULL, appPath, MAX_PATH);
        ::PathRemoveExtension(appPath);

        String file(m_DumpFilePath);
        file += _T("\\");
        file += ::PathFindFileName(appPath);
        file += _T("_") + m_AppVersion + _T("_");
        file += dt;
        file += _T(".dmp");
        return file;
    }

private:
    static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS* ep)
    {
        LONG ret = EXCEPTION_CONTINUE_SEARCH;

        TCHAR dbgHelpDLL[MAX_PATH];
        ::GetModuleFileName(NULL, dbgHelpDLL, MAX_PATH);

        ::PathRemoveFileSpec(dbgHelpDLL);
        ::PathAppend(dbgHelpDLL, _T("dbghelp.dll"));

        HMODULE module = ::LoadLibrary(dbgHelpDLL);
        if (module == NULL)
		{
			::MessageBox(NULL, _T("提示"), _T("缺少dbghelp.dll"), MB_TOPMOST | MB_ICONSTOP);
            return ret;
		}

        PFNWRITEDUMP MiniDumpWriteDump = (PFNWRITEDUMP)::GetProcAddress(module, "MiniDumpWriteDump");
        if (MiniDumpWriteDump != NULL)
        {
            String dumpFile = MiniDumper::Get()->GetDumpFile();
            HANDLE file = ::CreateFile(dumpFile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
                                       FILE_ATTRIBUTE_NORMAL, NULL);
            if (file == INVALID_HANDLE_VALUE)
                return ret;

            _MINIDUMP_EXCEPTION_INFORMATION mdei;
            mdei.ThreadId = ::GetCurrentThreadId();
            mdei.ExceptionPointers = ep;
            mdei.ClientPointers = NULL;

            MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
                                                MiniDumpWithDataSegs |
                                                MiniDumpWithHandleData |
                                                MiniDumpWithFullMemoryInfo |
                                                MiniDumpWithThreadInfo /*|
                                                MiniDumpWithUnloadedModules*/);

            if (MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), file, mdt, &mdei, NULL, NULL))
            {
                ::MessageBox(NULL, dumpFile.c_str(), _T("Crash Report!"), MB_TOPMOST | MB_ICONSTOP);
                const String openDmp(_T("/select,") + dumpFile);
                ::ShellExecute(NULL, _T("open"), _T("explorer.exe"), openDmp.c_str(), NULL, SW_SHOWNORMAL);
                ret = EXCEPTION_EXECUTE_HANDLER;
            }

            CloseHandle(file);
        }

        return ret;
    }

private:
    String m_DumpFilePath;
    String m_AppVersion;
};

} // namespace qp

#endif // _MSC_VER

#endif // INCLUDE_MINIDUMPER_H_
使用Dbg::MiniDumper::Get()->Init(); 也可以指定路径和版本