How to quit application in AppDomain.CurrentDomain.UnhandledException handler and still ensure that finally{} blocks execute?

StackOverflow https://stackoverflow.com/questions/18533360

Question

I wish to prevent "application has stopped working" popup from appearing whenever an exception occurs. One way to do this is obviously calling Environment.Exit(1) in a global exception handler, i.e. AppDomain.CurrentDomain.UnhandledException like this:

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{            
    Exception exc = (Exception)e.ExceptionObject;
    Console.Error.WriteLine("Exception:\n{0}", exc.Message);
    Console.Error.WriteLine("Stack trace:\n{0}", exc.StackTrace);

    Environment.Exit(1);    // quit silently on exception, don't show the popup                    
}

However, the above code results in finally blocks not executing due to the order of execution. A simple example of such behavior:

    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
    try
    {
        Console.WriteLine("try block");
        throw new Exception("Somebody set us up the bomb.");
    }
    catch
    {
        Console.Error.WriteLine("catch block");
        throw;
    }
    finally
    {
        Console.WriteLine("finally block");
    }

Environment.Exit(1) in the exception handler results in this output (notice no finally block) before application quits:

try block
catch block
Exception:
      Somebody set us up the bomb.
Stack trace:
       at ...

This can cause serious problems when it is critical that finally block executes, e.g. when cleaning up temp files created inside try.

Is there a simple way around all this? That is, keep global exception handler, customize exception output etc. inside it and and then exit gracefully, but still get finally blocks to execute. I find it weird that this problem has not been mentioned in questions like this.

Was it helpful?

Solution

You are not going to get this. Environment.Exit() ensures that finalizers still run, that could be the fallback. But not for cleaning up temporary files, use the operating system support for that and use the FileOptions.DeleteOnClose option.

In general you should never rely on a hard requirement for cleanup, nothing is getting cleaned-up when the CLR bombs with SOE or FEEE, the user terminates you app from Task Manager, hard-reboots the machine or the power goes off.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top