Unhandled exceptions in infinite loop - c#

I have a problem that I cannot seem to solve for a project. Consider this code:
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionsHandler);
int[] a = { 0, 1, 2 };
int y = a[6];
}
public static void UnhandledExceptionsHandler(object sender, UnhandledExceptionEventArgs e)
{
try
{
File.AppendAllText("Exceptions.log", (e.ExceptionObject as Exception).Message);
}
catch (Exception ex)
{
Environment.Exit(1);
}
}
}
}
The unhandled exception handler does in fact grab the unhandled exception as desired and write the message to log file. But on exiting the handler, the code resumes with the index out of range line: int y = a[6]. I need code to either move to the next line of code, or continue with the unhandled exception normally - in this case terminating the app. As it is, I'm stuck in an infinite loop of throw unhandled exception/hit the unhandled exception event handler.

You want try..finally in your handler:
try {
File.AppendAllText("Exceptions.log", (e.ExceptionObject as Exception).Message);
}
finally {
Environment.Exit(1);
}
What you have now is only catching an error that occurs when writing the log file. If there is no error (which there isn't).. it will finish the method and bubble back to the original exception.

Related

how call a function when an exception has occurred and the C# program has stopped?

In a C# program, I want to do some action,when an exception happens; that is when an exception happens and exception window appears, I want to screen capture it and save the image(and other info such as the time and user running the program)of the exception in the db.
Please note that in situation an exception occurs, the program stops until for the user clicks on the button(and if the user clicks on Quit button the app will end).
Your error says Unhandled Exception.
Just put your code in try catch block, and handle it accordingly
try
{
int zero = 0;
double i = (1/zero);
}
catch(Exception ex)
{
//ex contains your error and you can do whatever when you catch it in here
Console.WriteLine("Error: {0}", ex.Message);
}
If you want to catch all unhandled exceptions then you can use the application thread exception method.
In your program.cs you need to register the thread exception, and add a method to do your handling.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//Register your thread exception method here
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args));
}
//This method will then be called and you can handle your exception anyway you wish
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
//Add your custom handling code here
}
}

Why does AggregateException thrown from GUI thread get "unwrapped" in app exception handler?

I have a WinForm async GUI app in which I've set up some "global" exception handling in program.cs. I also have a GUI thread that's doing an "await Task.WhenAll()" and catching its exception and throwing the awaited Task.Exception property, so that the AggregateException gets all the way to the exception handler in program.cs (I want to iterate over the inner exceptions and log them).
I can see that the exception being thrown out of my try/catch of the WhenAll() is indeed throwing an AggreateException, but when I debug the handler in program.cs, it's not an AggregateException anymore - it's just the first Exception of the AggregateException. I can't figure out what code is doing this "unwrapping" for me?
Program.cs:
static void Main() {
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
...
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) {
if (e.Exception is AggregateException) {
// expect to log the contents of (e.Exception as AggregateException).Flatten().InnerExceptions, but exception coming
// in is not AggregateException but instead is
// ApplicationException("message 1")
}
else {
// handling for non aggregate exceptions
}
In Form1.cs
private async void button1_Click(object sender, EventArgs e) {
Task overall = Task.WhenAll(
Task.Run(()=> { throw new ApplicationException("message 1"); }),
Task.Run(() => { throw new ApplicationException("message 2"); })
);
try {
await overall;
}
catch {
throw overall.Exception; // this is AggregateException
}
}
}
It's not just AggregateException - WinForms will always only send GetBaseException() to the handler. That is, only the innermost exception of any InnerException chain.
Apparently this is a longstanding WinForms bug, probably permanent at this point.
You'll have to work around it with your own type:
public class ExceptionWrapper : Exception
{
public new Exception InnerException { get; set; }
}
throw new ExceptionWrapper { InnerException = overall.Exception };
The best possible workaround for this issue is capturing the raised exception via the AppDomain.FirstChangeException event and then comparing this exceptions base exception reference against the exception raised by Application.ThreadException.
Something like this:
private Exception lastFirstChanceException;
AppDomain.CurrentDomain.FirstChanceException += (sender, e) =>
{
lastFirstChanceException = e.Exception;
};
Application.ThreadException += (sender, e) =>
{
if (lastFirstChanceException?.GetBaseException() == e.Exception)
{
var realException = lastFirstChanceException; // This is the "real" exception thrown by some code
}
};

How to ensure log the exception when there is unhandled exception

I want a crash reporting, so I register the UnhandledException event in App.xaml.cs like following. But there are 2 problems:
Sometimes, there is no callstacks for exception
Sometimes, I don't have enough time to write log into file before the process is terminated.
Any advice?
this.UnhandledException += App_UnhandledException;
private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (!hasHandledUnhandledException)
{
e.Handled = true;
_logger.Error("Unhandle exception - message = {0}\n StackTrace = {1}", e.Exception.Message, e.Exception.StackTrace);
await CrashHandler.ReportExceptionAsync(e.Exception.Message, e.Exception.StackTrace);
hasHandledUnhandledException = true;
throw e.Exception;
}
}
Make sure to access e.Exception only once. In some cases, information about the stacktrace is lost the second time you access the property. Save the exception in a variable and work directly with that variable. Also, as mentioned by Panagiotis Kanavos in the comments, directly log e.Exception.ToString() to make sure to miss no information. This will include the message, the callstack, and all inner exceptions (which you are not logging in your current code).
private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (!hasHandledUnhandledException)
{
e.Handled = true;
var exception = e.Exception;
_logger.Error("Unhandled exception - {0}", exception);
await CrashHandler.ReportExceptionAsync(exception.Message, exception.StackTrace);
hasHandledUnhandledException = true;
throw e.Exception;
}
}
As for the problem of not having enough time to log the exception, it's controlled by the runtime so you can't do anything about it.

catching unhandled exceptions in csharp

I am getting a NullReferenceException in release mode, but not in debug mode.
To try and find the error, I have added an UnhandledException handler, however the exception is not sent to the handler.
There is no gui code, it is console only.
The program exits with the message:
System.NullReferenceException: Object reference not set to an instance of an object.
To be clear, I don't get this in debug mode at all, I only get it when it is run in release mode from the console, so I can't debug it to find where the problem is.
why does setting the AppDomain.CurrentDomain.UnhandledException not work?
static void errhandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine(e.StackTrace + ' ' + e.ToString());
System.Environment.Exit(1);
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Flags = System.Security.Permissions.SecurityPermissionFlag.ControlAppDomain)]
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=new UnhandledExceptionEventHandler(errhandler);
try
{
new test(args[0], args[1]);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace + ' ' + e.ToString());
}
}
For handling ALL exceptions we use this:
private static void SetupExceptionHandling()
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += ApplicationThreadException;
// Set the unhandled exception mode to force all Windows Forms errors to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += AppDomainUnhandledException;
// This AppDomain-wide event provides a mechanism to prevent exception escalation policy (which, by default, terminates the process) from triggering.
// Each handler is passed a UnobservedTaskExceptionEventArgs instance, which may be used to examine the exception and to mark it as observed.
TaskScheduler.UnobservedTaskException += TaskSchedulerUnobservedTaskException;
// Add the event handler for handling UI thread exceptions to the event.
Dispatcher.CurrentDispatcher.UnhandledException += DispatcherUnhandledException;
}
I hope, it may help you.
Your code is correct. Proof:
static void errhandler(object sender, UnhandledExceptionEventArgs args)
{
Console.WriteLine("Errhandler called");
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine(e.StackTrace + ' ' + e.ToString());
System.Environment.Exit(1);
}
public static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(errhandler);
string s = null;
s.ToString();
}
prints "Errhandler called".
Thus, your problem is somewhere else.
Why not put a try catch block in the code?
Like this:
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, Flags = System.Security.Permissions.SecurityPermissionFlag.ControlAppDomain)]
static void Main(string[] args)
{
try
{
new test(args[0], args[1]);
}
catch(Exception e)
{
Console.WriteLine(e)
}
}
Or do you need to use a Eventhandler?

.NET Global exception handler in console application

Question: I want to define a global exception handler for unhandled exceptions in my console application. In asp.net, one can define one in global.asax, and in windows applications /services, one can define as below
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyExceptionHandler);
But how can I define a global exception handler for a console application ?
currentDomain seems not to work (.NET 2.0) ?
Edit:
Argh, stupid mistake.
In VB.NET, one needs to add the "AddHandler" keyword in front of currentDomain, or else one doesn't see the UnhandledException event in IntelliSense...
That's because the VB.NET and C# compilers treat event handling differently.
No, that's the correct way to do it. This worked exactly as it should, something you can work from perhaps:
using System;
class Program {
static void Main(string[] args) {
System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
throw new Exception("Kaboom");
}
static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) {
Console.WriteLine(e.ExceptionObject.ToString());
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
Environment.Exit(1);
}
}
Do keep in mind that you cannot catch type and file load exceptions generated by the jitter this way. They happen before your Main() method starts running. Catching those requires delaying the jitter, move the risky code into another method and apply the [MethodImpl(MethodImplOptions.NoInlining)] attribute to it.
If you have a single-threaded application, you can use a simple try/catch in the Main function, however, this does not cover exceptions that may be thrown outside of the Main function, on other threads, for example (as noted in other comments). This code demonstrates how an exception can cause the application to terminate even though you tried to handle it in Main (notice how the program exits gracefully if you press enter and allow the application to exit gracefully before the exception occurs, but if you let it run, it terminates quite unhappily):
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void DemoThread()
{
for(int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
You can receive notification of when another thread throws an exception to perform some clean up before the application exits, but as far as I can tell, you cannot, from a console application, force the application to continue running if you do not handle the exception on the thread from which it is thrown without using some obscure compatibility options to make the application behave like it would have with .NET 1.x. This code demonstrates how the main thread can be notified of exceptions coming from other threads, but will still terminate unhappily:
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Notified of a thread exception... application is terminating.");
}
static void DemoThread()
{
for(int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
So in my opinion, the cleanest way to handle it in a console application is to ensure that every thread has an exception handler at the root level:
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void DemoThread()
{
try
{
for (int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception on the other thread");
}
}
You also need to handle exceptions from threads:
static void Main(string[] args) {
Application.ThreadException += MYThreadHandler;
}
private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e)
{
Console.WriteLine(e.Exception.StackTrace);
}
Whoop, sorry that was for winforms, for any threads you're using in a console application you will have to enclose in a try/catch block. Background threads that encounter unhandled exceptions do not cause the application to end.
I just inherited an old VB.NET console application and needed to set up a Global Exception Handler. Since this question mentions VB.NET a few times and is tagged with VB.NET, but all the other answers here are in C#, I thought I would add the exact syntax for a VB.NET application as well.
Public Sub Main()
REM Set up Global Unhandled Exception Handler.
AddHandler System.AppDomain.CurrentDomain.UnhandledException, AddressOf MyUnhandledExceptionEvent
REM Do other stuff
End Sub
Public Sub MyUnhandledExceptionEvent(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
REM Log Exception here and do whatever else is needed
End Sub
I used the REM comment marker instead of the single quote here because Stack Overflow seemed to handle the syntax highlighting a bit better with REM.
What you are trying should work according to the MSDN doc's for .Net 2.0. You could also try a try/catch right in main around your entry point for the console app.
static void Main(string[] args)
{
try
{
// Start Working
}
catch (Exception ex)
{
// Output/Log Exception
}
finally
{
// Clean Up If Needed
}
}
And now your catch will handle anything not caught (in the main thread). It can be graceful and even restart where it was if you want, or you can just let the app die and log the exception. You woul add a finally if you wanted to do any clean up. Each thread will require its own high level exception handling similar to the main.
Edited to clarify the point about threads as pointed out by BlueMonkMN and shown in detail in his answer.

Categories