当进程崩溃时生成崩溃转储的最佳方式



Windows环境(XPWin 7)中:

  • 当进程在系统上崩溃时,自动生成崩溃转储的最佳方法是什么
  • 安装程序(MSI)包能做到这一点吗

在Windows上为任何/特定进程自动转储的最佳方法之一是在注册表中配置一组条目。我在Windows 7 64位上尝试了以下操作。

打开notepad.exe,粘贴下面的条目并将其保存为"EnableDump.reg"。您可以提供任何您想要的名称。

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsWindows Error ReportingLocalDumps]
"DumpFolder"=hex(2):44,00,3a,00,5c,00,64,00,75,00,6d,00,70,00,00,00
"DumpCount"=dword:00000010
"DumpType"=dword:00000002
"CustomDumpFlags"=dword:00000000

双击"EnableDump.reg"并选择"是"。我已将转储文件夹指定为"d:\dump"。您可以将其更改为您想要的任何文件夹。

尝试执行崩溃的应用程序,Windows将显示错误对话框。选择"关闭程序"选项。之后,您将在配置的文件夹中看到转储。转储文件的名称将是.exe..dmp.

有关更多详细信息,您可以参考下面的链接。

http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx

以下解释基于另一个答案,但逻辑是我的(正如我的个人资料所说,无需归因);

拥有自己的转储生成框架,当遇到任何未处理的异常时,该框架会自动创建进程转储,这将避免客户端必须安装WinDbg

在应用程序启动时,使用SetUnhandledExceptionFilter(...) Win32 API注册回调(即应用程序级异常处理程序)。现在,只要有任何未处理的异常,就会调用已注册的回调函数。然后,您可以使用DbgHelp.dll中的MiniDumpWriteDump(...) API创建流程转储。

C++示例(启用unicode)

头文件

#ifndef CRASH_REPORTER_H
#define CRASH_REPORTER_H
//Exclude rarely used content from the Windows headers.
#ifndef WIN32_LEAN_AND_MEAN
#    define WIN32_LEAN_AND_MEAN
#    include <windows.h>
#    undef WIN32_LEAN_AND_MEAN
#else
#    include <windows.h>
#endif
#include <tchar.h>
#include <DbgHelp.h>
class CrashReporter {
public:
    inline CrashReporter() { Register(); }
    inline ~CrashReporter() { Unregister(); }
    inline static void Register() {
        if(m_lastExceptionFilter != NULL) {
            fprintf(stdout, "CrashReporter: is already registeredn");
            fflush(stdout);
        }
        SetErrorMode(SEM_FAILCRITICALERRORS);
        //ensures UnHandledExceptionFilter is called before App dies.
        m_lastExceptionFilter = SetUnhandledExceptionFilter(UnHandledExceptionFilter);
    }
    inline static void Unregister() {
        SetUnhandledExceptionFilter(m_lastExceptionFilter);
    }
private:
    static LPTOP_LEVEL_EXCEPTION_FILTER m_lastExceptionFilter;
    static LONG WINAPI UnHandledExceptionFilter(_EXCEPTION_POINTERS *);
};

#endif // CRASH_REPORTER_H

源文件

#include "crash-report.h"
#include <stdio.h>
LPTOP_LEVEL_EXCEPTION_FILTER CrashReporter::m_lastExceptionFilter = NULL;
typedef BOOL (WINAPI *MiniDumpWriteDumpFunc)(HANDLE hProcess, DWORD ProcessId
        , HANDLE hFile
        , MINIDUMP_TYPE DumpType
        , const MINIDUMP_EXCEPTION_INFORMATION *ExceptionInfo
        , const MINIDUMP_USER_STREAM_INFORMATION *UserStreamInfo
        , const MINIDUMP_CALLBACK_INFORMATION *Callback
    );
LONG WINAPI CrashReporter::UnHandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtr)
{
    //we load DbgHelp.dll dynamically, to support Windows 2000
    HMODULE hModule = ::LoadLibraryA("DbgHelp.dll");
    if (hModule) {
        MiniDumpWriteDumpFunc dumpFunc = reinterpret_cast<MiniDumpWriteDumpFunc>(
                    ::GetProcAddress(hModule, "MiniDumpWriteDump")
                );
        if (dumpFunc) {
            //fetch system time for dump-file name
            SYSTEMTIME  SystemTime;
            ::GetLocalTime(&SystemTime);
            //choose proper path for dump-file
            wchar_t dumpFilePath[MAX_PATH] = {0};
            _snwprintf_s(dumpFilePath, MAX_PATH, L"crash_%04d-%d-%02d_%d-%02d-%02d.dmp"
                    , SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay
                    , SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond
                );
            //create and open the dump-file
            HANDLE hFile = ::CreateFileW( dumpFilePath, GENERIC_WRITE
                    , FILE_SHARE_WRITE
                    , NULL
                    , CREATE_ALWAYS
                    , FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN
                    , NULL
                );
            if (hFile != INVALID_HANDLE_VALUE) {
                _MINIDUMP_EXCEPTION_INFORMATION exceptionInfo;
                exceptionInfo.ThreadId          = GetCurrentThreadId();
                exceptionInfo.ExceptionPointers = exceptionPtr;
                exceptionInfo.ClientPointers    = NULL;
                //at last write crash-dump to file
                bool ok = dumpFunc(::GetCurrentProcess(), ::GetCurrentProcessId()
                        , hFile, MiniDumpNormal
                        , &exceptionInfo, NULL, NULL
                    );
                //dump-data is written, and we can close the file
                CloseHandle(hFile);
                if (ok) {
                    //Return from UnhandledExceptionFilter and execute the associated exception handler.
                    //  This usually results in process termination.
                    return EXCEPTION_EXECUTE_HANDLER;
                }
            }
        }
    }
    //Proceed with normal execution of UnhandledExceptionFilter.
    //  That means obeying the SetErrorMode flags,
    //  or invoking the Application Error pop-up message box.
    return EXCEPTION_CONTINUE_SEARCH;
}

用法

#include "3rdParty/crash-report.h"
int main(int argc, char *argv[])
{
    CrashReporter crashReporter;
    (void)crashReporter; //prevents unused warnings
    // [application main loop should be here]
    return 0;
}

Windows XP:以下步骤启用自动崩溃转储:

1) Open a command prompt, running as administrator
2) Run drwtsn32 -i. This will install Doctor Watson as the default debugger when something crashes
3) Click Ok
4) From the command prompt, run drwtsn32
5) Set the Crash Dump path to your favorite directory, or leave the default.
6) Set the Crash Dump Type to mini. Note that under some circumstances, we may ask you for a full crash dump.
7) Make sure the Dump All Thread Contexts and Create Crash Dump File options are selected.
8) Click Ok
9) If a user.dmp file already exists in the Crash Dump path, delete it.

Windows 7:位置为:

C:Users[Current User when app crashed]AppDataLocalMicrosoftWindowsWERReportArchive

相关内容

  • 没有找到相关文章