c# - C# WinForm static void Main 不能捕获异常吗?

标签 c# winforms exception

我有一个用 C# 编写的 WinForm 应用程序,我在其中放置了一个 try-catch block 到 Program.cs,在程序入口中,static void Main 方法,就在应用程序的开头,如下所示:

using System;
using System.IO;
using System.Windows.Forms;

namespace T5ShortestTime {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            try {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new T5ShortestTimeForm());
            } catch (Exception e) {
                string errordir = Path.Combine(Application.StartupPath, "errorlog");
                string errorlog = Path.Combine(errordir, DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ".txt");
                if (!Directory.Exists(errordir))
                    Directory.CreateDirectory(errordir);                
                File.WriteAllText(errorlog, e.ToString());              
            }
        }
    }
}

如您所见,Application 被放入 try-catch block 和 catch block 中,它唯一做的事情就是创建错误日志文件。

现在,到目前为止一切顺利。我的应用程序运行良好,如果我遇到崩溃,最后一个 Exception 应该被 try-catch block 捕获并存储在错误日志文件中。

但是,当我运行我的程序一段时间后,我遇到了一个未处理的异常(null 引用)。令我惊讶的是异常不会创建错误日志文件。

现在,this post显示它可能是由 ThreadExceptionHandleProcessCorruptedStateExceptions(两个最受好评的答案)引起的,但我的案例显示了一个简单的 null 引用异常:

Problem signature:
  Problem Event Name:   CLR20r3
  Problem Signature 01: T5ShortestTime.exe
  Problem Signature 02: 2.8.3.1
  Problem Signature 03: 5743e646
  Problem Signature 04: T5ShortestTime
  Problem Signature 05: 2.8.3.1
  Problem Signature 06: 5743e646
  Problem Signature 07: 182
  Problem Signature 08: 1b
  Problem Signature 09: System.NullReferenceException
  OS Version:   6.3.9600.2.0.0.272.7
  Locale ID:    1033
  Additional Information 1: bb91
  Additional Information 2: bb91a371df830534902ec94577ebb4a3
  Additional Information 3: aba1
  Additional Information 4: aba1ed7202d796d19b974eec93d89ec2

Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=280262

If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt

为什么会这样?

最佳答案

the last Exception should be captured by the try-catch block

那是不会发生的。除了在一种情况下,当您在附加调试器的情况下运行程序时。所以你肯定被哄骗相信它会起作用,每个人总是开始使用 F5 运行他们的程序一段时间。

Application.Run() 在其引发事件的代码中有一个后备程序,try/catch-em-all 在事件处理程序抛出未处理的异常时引发 Application.ThreadException 事件。该后退器确实、真的 是必要的,尤其是在 x64 版本的 Windows 7 上。Very Bad Things happen当没有异常处理程序时。然而,当您使用调试器运行时,该后退停止器不存在,这使得未处理的异常难以调试。

因此,当您调试时,您的 catch 子句将运行。使未处理的异常难以调试。当您在没有调试器的情况下运行时,您的 catch 子句将运行并且您的程序将崩溃,正如您所描述的那样。使未处理的异常难以调试。

所以不要这样做。 Application.Run() 如何处理未处理的异常是使用 Application.SetUnhandledExceptionMode() 方法配置的。你会更喜欢这个版本:

    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        if (!System.Diagnostics.Debugger.IsAttached) {
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
            AppDomain.CurrentDomain.UnhandledException += LogException;
        }
        Application.Run(new Form1());
    }

    private static void LogException(object sender, UnhandledExceptionEventArgs e) {
        string errordir = Path.Combine(Application.StartupPath, "errorlog");
        string errorlog = Path.Combine(errordir, DateTime.Now.ToString("yyyyMMdd_HHmmss_fff") + ".txt");
        if (!Directory.Exists(errordir))
            Directory.CreateDirectory(errordir);
        File.WriteAllText(errorlog, e.ToString());
        AppDomain.CurrentDomain.UnhandledException -= LogException;
        MessageBox.Show("Error details recorded in " + errorlog, "Unexpected error");
        Environment.Exit(1);
    }

有了这段代码,您就可以毫无问题地调试未处理的异常。 Debugger.IsAttached 测试确保调试器在事件处理程序失败时始终停止。如果没有调试器,它会禁用 Application.ThreadException 事件(这是非常无用的)并支持监听所有 异常。包括在工作线程中提出的那些。

您应该向用户发出警告,这样窗 Eloquent 不会消失得无影无踪。我打算推荐 MessageBox 但注意到 this bug目前又回到了 Windows 10 上。唉。

关于c# - C# WinForm static void Main 不能捕获异常吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37428235/

相关文章:

c# - 案例陈述的更好替代方案

c# - 无法访问 Task.Run 中已处置的对象

c# - 更改数据集中记录的顺序

python - 在 python 的自定义错误类中调用 super 有什么意义?

c# - 如何合并两个列表的内容?

c# - 如何在不获取焦点的情况下将表单放置在另一个表单之上

c# - 减少闪烁时使用 C# Listview 模糊文本

c# - C# WinForms 应用程序中未发生预期的跨线程异常

c++ - (不)在异常中使用 std::string

exception - 无法在本地运行 Sonatype Nexus