如何在 Windows 表单应用程序中获取故障转储

How to get a crash dump in Windows Form application

注意:这不是 Is there a setting that is preventing the unhandled exception dialog from displaying in apps that I compile? 的重复,因为 post 问的是相反的问题(如何获得我想删除的对话框)和提供的答案,尽管它们提供了一些与我的问题相关的信息,它没有回答以下问题:当 Windows 表单事件抛出未处理的异常时,我如何让我的应用程序创建故障转储。

我不明白为什么会有人希望那里的用户看到这个对话框。

但这不是本post的重点。如何让我的应用程序生成故障转储?我想不通。

编辑:比方说,我的可执行文件是myapplication.exe。当它崩溃时,我希望 WERFAULT.EXE 处理它,这样它就会创建一个故障转储,我的客户可以将其发送给我,以便我调查问题。如果我从我的一个线程中抛出一个未处理的异常,我会得到一个故障转储。但是,当我从 Windows Form 事件中抛出未处理的异常时,会显示上面的对话框。

我创建了一个 myapplication.exe.config 文件并按照此对话框详细信息底部的指示输入以下内容。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.windows.forms jitDebugging="true" />
</configuration>

我把 myapplication.exe.config 文件放在我的安装目录中,除了我的 application.exe 文件。

现在应用程序消失了。没有故障转储,即使我将注册表配置为创建故障转储。按照指示 here

在我的安装程序中,我创建了必要的注册表更改以强制我的应用程序创建故障转储。在

HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\myapplication.exe

注册表项我将 DumpType 设置为 2,将 DumpFolder 设置为我们的应用程序数据目录,将 DumpCount 设置为 1。但是进程刚刚消失,没有创建故障转储。

我知道机器配置为正确创建故障转储,因为我可以将代码添加到其他应用程序以使其崩溃并正确创建故障转储。

编辑:如果我将我的主入口点 Application.SetUnhandledExceptionMode 添加到 UnhandledExceptionMode.ThrowException,我不会得到对话框,但该过程就会消失。没有故障转储。

回答了我自己的问题。据我所知,当 Windows 表单事件引发未处理的异常时,没有任何配置可以使 Windows 表单应用程序创建故障转储。但是您可以在代码中触发它。

.NET 捕获在其表单事件中抛出的异常并显示如上所示的 .NET 错误对话框。这可以由 Application.SetUnhandledExceptionMode and Application.ThreadException 事件处理程序控制。

我的解决方案的前提是处理线程异常事件并在windows表单事件之外重新抛出异常。如果未捕获异常,如果机器配置为这样做,它将创建故障转储。

唯一的缺点是堆栈跟踪不是初始异常发生时的堆栈跟踪,您无法从崩溃转储中抛出的异常对象中获取它。所以你会想在某处记录堆栈跟踪。

    private class ApplicationThreadException : Exception
    {
        public new Exception InnerException { get; internal set; }
        public ApplicationThreadException(Exception e)
        {
            InnerException = e;
        }
    }

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        throw new ApplicationThreadException(e.Exception);
    }

    [STAThread]
    static void Main(string[] args)
    {
        Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        try
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyForm());
        }
        catch (ApplicationThreadException e)
        {
            throw e.InnerException;
        }
        catch (Exception e)
        {
            // do what ever
        }
    }