我有一个用WinForm
编写的C#
应用程序,我在try-catch
中的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
块中,在catch
块中,它唯一能做的就是创建错误日志文件。
现在,到目前为止一切顺利。我的应用程序运行良好,如果遇到崩溃,Exception
块应捕获最后try-catch
并存储在错误日志文件中。
然而,当我运行我的程序一段时间后,我得到一个未处理的异常(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
为什么会这样?
答案 0 :(得分:5)
最后一个Exception应该被try-catch块
捕获
这不会发生。除了一种情况,当您运行附带调试器的程序时。所以你肯定会觉得它会起作用,每个人总是开始用F5运行他们的程序一段时间。
Application.Run()在其代码中有一个反向停止引发事件,try / catch-em-all在事件处理程序抛出未处理的异常时引发Application.ThreadException事件。实际上,确实是非常必要的,尤其是在没有异常处理程序的Windows 7的x64版本上。ExecutorService Examples。但是,当您使用调试器运行时,这种后退不存在,这使得未处理的异常难以调试。
因此,当您进行调试时,您的 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事件(它没用)并且倾向于收听所有异常。包括在工作线程中引发的那些。
你应该向用户发出警告,这样窗口就不会消失而没有任何痕迹。我打算推荐MessageBox,但注意到{10}目前在Windows 10上又回来了。叹气。
答案 1 :(得分:2)
ThreadException
不是类似(NullReferenceException
)的异常类型。就是这样:
此事件允许您的Windows窗体应用程序以其他方式处理 Windows窗体线程中出现未处理的异常
这意味着它处理主线程以外的线程中的异常。
因此,您还需要订阅:AppDomain.CurrentDomain.UnhandledException以便处理主线程中的异常(无论异常的类型如何NullReference
,IndexOutOfRange
等。 )。
答案 2 :(得分:2)
好的,最后我在Hans Passant中Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)
为VB.Net
实施了C#
。在这里,我为static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (!System.Diagnostics.Debugger.IsAttached) {
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
AppDomain.CurrentDomain.UnhandledException += LogUnhandledExceptions;
}
Application.Run(new T5ShortestTimeForm());
}
private static void LogUnhandledExceptions(object sender, UnhandledExceptionEventArgs e) {
Exception ex = (Exception)e.ExceptionObject;
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, ex.ToString());
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex));
}
添加了自己的代码+错误记录:
Exceptions
此外,这里似乎混淆的原因是实际上发生了两个传播System.Exception: Exception of type 'System.Exception' was thrown.
at T5ShortestTime.T5ShortestTimeForm..ctor() in C:\Test.cs:line 45
at T5ShortestTime.Program.Main() in C:\Test.cs:line 19
at ...
:
第一个是应用程序本身的任何异常:
Dispose
第二个发生在Form
组件的null
期间,这会产生另一个异常,它是System.NullReferenceException: Object reference not set to an instance of an object.
at T5ShortestTime.T5ShortestTimeForm.Dispose(Boolean disposing)
at System.ComponentModel.Component.Finalize()
引用异常:
NullReferenceException
因此,当我在我的应用中测试异常时,Dispose
位于UnhandledExceptionMode
的最后一位。
我将ThrowException
设置为上面的Expression<Func<T, bool>>
后,我才设法捕捉到这一点。