我有一个用 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显示它可能是由 ThreadException
或 HandleProcessCorruptedStateExceptions
(两个最受好评的答案)引起的,但我的案例显示了一个简单的 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/