【问题标题】:Best way to have crash dumps generated when processes crash?进程崩溃时生成崩溃转储的最佳方法?
【发布时间】:2022-02-19 00:27:07
【问题描述】:

Windows 环境中(XPWin 7):

  • 当系统上的进程崩溃时,自动生成崩溃转储的最佳方法是什么?
  • 安装程序 (MSI) 包可以执行此操作吗?

【问题讨论】:

  • 这是一个全局设置。单个程序的安装程序绝对不应更改全局设置。如果您的程序需要故障转储,请将逻辑放入您的程序中。

标签: windows windows-installer crash-dumps drwatson


【解决方案1】:

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

打开notepad.exe,粘贴以下条目并将其保存为“EnableDump.reg”。你可以给任何你想要的名字。

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"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

【讨论】:

  • 试试 XP。您可以编写一个 c++ 控制台应用程序并粘贴下面的代码。 int main( void ) { char pp;字符 tpp; strncpy(pp,tpp,5000);返回0;运行应用程序,它会崩溃。关闭 Windows 错误对话框。检查为转储文件配置的文件夹。
  • 根据微软文档,它只能从以下平台开始工作。 Windows Server 2008 和带有 Service Pack 1 (SP1) 的 Windows Vista。
  • 是的,如果您取消屏蔽除以零的浮点异常,除以零将起作用。默认情况下,运行时库会屏蔽所有浮点异常。
  • 似乎无法在 WIndows 7 Enterprise 64bit 上运行
  • @IgorMesaros:它在 Windows 7 Professional 64bit 上运行良好。 AFAIK,企业版在这种情况下没有任何区别。
【解决方案2】:

以下解释基于another answer,但逻辑是我的(无需署名,如我的个人资料所述);

拥有自己的转储生成框架,在遇到任何未处理异常时自动创建进程转储,可以避免客户端安装WinDbg

在应用程序启动时使用SetUnhandledExceptionFilter(...) Win32 API 来注册回调(即应用程序级异常处理程序)。 现在,只要有任何未处理的异常,就会调用注册的回调函数。然后,您可以使用来自DbgHelp.dllMiniDumpWriteDump(...) 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 registered\n");
            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;
}

【讨论】:

    【解决方案3】:

    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]\AppData\Local\Microsoft\Windows\WER\ReportArchive
    

    【讨论】:

    • MSI 包可以应用这个配置吗?
    • 在什么情况下?你想让你的程序转储错误吗?
    • 是的,我希望崩溃生成崩溃转储。这可能是 MSI 安装程序可以应用的注册表更改。
    • 你指的是所有崩溃的进程还是你开发的进程/程序?
    • 我想为我的程序生成故障转储。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    相关资源
    最近更新 更多