I have a WinForm
application written in C#
where I put a try-catch
block in the Program.cs
, in the program entry, the static void Main
method, right in the beginning of the application like this:
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());
}
}
}
}
As you can see, the Application
is put in a try-catch
block and in the catch
block, the only thing it does is to create an error log file.
Now, so far so good. My application is running well and if I encounter a crash, the last Exception
should be captured by the try-catch
block and stored in the error log file.
However, as I run my program for a while, I get an unhandled exception (null
reference). What surprise me is that the exception does not create an error log file.
Now, this post shows that it is possibly caused by ThreadException
or HandleProcessCorruptedStateExceptions
(the two most upvoted answers), but my case shows a simple null
reference exception:
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
Why would that be?
the last Exception should be captured by the try-catch block
That is not going to happen. Except in one case, when you run your program with a debugger attached. So you surely got lulled into believing it would work, everybody always starts out running their program with F5 for a while.
Application.Run() has a back-stop in its code that raises events, try/catch-em-all that raises the Application.ThreadException event when an event handler throws an unhandled exception. That back-stop is really, really necessary, especially on the x64 version of Windows 7. Very Bad Things happen when there is no exception handler. That back-stop is however not in place when you run with the debugger, that makes unhandled exceptions too difficult to debug.
So when you debug then your catch clause will run. Making unhandled exceptions too difficult to debug. When you run without a debugger then your catch clause will not run and your program will crash, just as you described. Making unhandled exception too difficult to debug.
So don't do it this way. How Application.Run() deals with unhandled exceptions is configured with the Application.SetUnhandledExceptionMode() method. You'll like this version better:
[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);
}
With this code in place, you can debug unhandled exceptions without any problems. The Debugger.IsAttached test ensures that the debugger will always stop when an event handler falls over. Without a debugger, it then disables the Application.ThreadException event (it is quite useless) and favors listening to all exceptions. Including the ones raised in worker threads.
You ought to give an alert to the user so the window doesn't just disappear without any trace. I was going to recommend MessageBox but noticed that this bug is currently back again on Windows 10. Sigh.
ThreadException
is not an exception type like (NullReferenceException
). It is that:
This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads
This means that it handles exceptions in threads other than the Main Thread.
So, you need to subscribe to : AppDomain.CurrentDomain.UnhandledException also in order to handle the exceptions in your Main Thread (Regardless of the type of the exception e.g. NullReference
, IndexOutOfRange
, etc..).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With