tags:

views:

2758

answers:

11

Hi Guys, i wonder how can i write a catch'em all exception handler in the application level which will give the user the option to resume the application flow?

Thanks!!!

A: 

This just screams bad design all over. Never use exceptions for things like this. Exceptions are ONLY to be used when something the programmer did not intend to occures.

If you want error-handling. dont use exceptions like this, rahter build a system where you save states and can go back to states etc... but using exceptions for state handling, bad idea.

Filip Ekberg
I don't think the question suggests using exceptions in an inappropriate way at all. It's simply a case of "something's gone wrong... well, let's see where we can continue from." That seems a pretty natural concept - it's just difficult to implement robustly, and very application-dependent.
Jon Skeet
I agree with Jon, this approach would be useful for logging unexpected exceptions (for example error reporting). There are very legitimate and useful reasons for this kind of approach.
DoctaJonez
Agree with Jon. I think some people are idealizing a little.
Sam Meldrum
Ok having that perspective i can see how it is usefull. However, for error-reporting i'd rathoer Not use a general "catch em' all"-exception.When i visualize this i see: try{ /* everything goes here */ } catch(Exception ex) somewhat like that, which imho would be bad design. But sure is discussable
Filip Ekberg
@Filip, you're right;when we use a try..catch we should be specific about what we want/expect to catch. The question being raised in the post is for when we get an exception that we weren't expecting we want to log it and handle it elegantly rather than let the JIT debugger scare the user.
DoctaJonez
+7  A: 

It depends on what you mean by "resume". The trouble with exceptions is that unless you're very careful, by the time an exception happens your application state is quite possibly corrupt - you might have completed half an operation.

If you can isolate your operations - much like a database isolates transactions - then you can effectively let your user resume from the "last commit point". That will very much depend on the type of your application though. Could you give us more details about the kind of application you're building?

Jon Skeet
Only Jon Skeet could have the most upvotes with an answer asking for more info ;P
Jon B
The only way I know to do what Adi wants, repsecting what Jon Skeet pointed out - is to have transactional operations on everything - which I've seen some crazy implementations of.
Matt Cruikshank
+1  A: 

Add a handler to the Application.ThreadException event.

Vincent Van Den Berghe
This answer is correct. No idea why it's been downvoted. :-( perhaps people are downvoting because they don't think this should be done. That's all very well, but this does actually answer the question.
Sam Meldrum
+2  A: 

I don't think this is really feasible using a global error handler. You need to figure out what kind of errors are recoverable at different points in your application and write specific error handlers to address the errors as they occur -- unless you want to resort to application restart, which may or may not work depending on what the actual error is. In order to do any kind of resume, you'll need to save enough state to restart from a known good state.

tvanfosson
A: 

I'm building a C# winform and i handle most exceptions myself, however i don't want my application to just crash when an unjhandled exception occures. i want to write to the log, do some checkings and resume the application to a stable point of my choice. I DONT WANT TO SIMPLY CRASH! Now, microsoft do it for me but i don't like their default form. I want to handle it myself.

Thanks Guys!

You need to attach an event to Application.ThreadExceptionThen you can do your logging etc. Would advise shutdown after this rather than allowing user to continue. See answer I posted with sample code.
Sam Meldrum
Can you edit the question to include this Answer? You may get better answers that way.
Sam Meldrum
A: 

What about AppDomain.CurrentDomain.UnhandledException - can i use it?

Only works in 1.1 and that's only cause its bugged.
Quibblesome
A: 

If you use Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase you can handle the UnhandledExeption event. The args for this event include a bool used to decide if you want to exit the application.

I realize you're using c#, but you can still use the Microsoft.VisualBasic namespace.

I agree with other posters that this might be sloppy, but I also understand you don't want the default .NET dialog to show.

Jon B
A: 

Microsoft Enterprise Library Exception Handling Application Block has examples of how you can do this.

Basically you surround the code that can throw exceptions with this:

try
{
  MyMethodThatMightThrow();
}
catch(Exception ex)
{
   bool rethrow = ExceptionPolicy.HandleException(ex, "SomePolicy");
   if (rethrow) throw;
}

Then you can configure the Policy to show a dialog to the user and ask if she wants to continue.

You still need to put try catch blocks around in your code at points where you believe you are at a consistent state.

Hallgrim
A: 

In some versions of .NET you can actually put a catcher around the Application.Run() (you'll find this in program.cs) and this should catch all the Main Thread's exceptions however in most cases this maybe poor design and wont give you much of an opportunity to "resume". Additionally you will always have to manually handle any exceptions on background threads.

You can design an app to "catch all" and display a common error message and debug info, this is fine as long as you exit afterwards. What is highly discouraged is making a "resume" available to the user as this will probably give you more problems in the long-run.

Quibblesome
A: 

You should read up on all the problems associated with VB's "On Error Resume Next" style of error handling. It sounds like you're trying to implement this for C#.

Even if you can resume from the point of where the exception is generated, this is a broken technique for error handling. There's no way for a global handler to actually be able to handle any error/exception - it can't possibly know what's required for any arbitrary situation.

You would have to set some sort of global variable, and have the mainline code continually check it for error indications (ie., use the VB technique).

I think the best you can do to recover from an error like you're describing is to catch the exception at the application level, log the problem, inform the user (and potentially generate/send some sort of problem report for you), and restart the application. Of course, if you catch the exception closer to the problem area, that handler has a chance to do something a bit more intelligent, so you should not rely on the app-level handler as a crutch - just as a fail-safe.

Michael Burr
+4  A: 

I assume you are writing a Windows application in which case, yes, you can do this. I will leave the rights and wrongs of whether or not you should to others. There are already enough answers which look at this and I suggest you consider them carefully before you actually do this.

Note, that this code will behave differently in the debugger than it does if you run the application directly (another reason not to do it perhaps). To get the application to show the messagebox and to continue on thereafter you will need to run the application from explorer, not from visual studio.

Create a new Windows forms application. The code in Program.cs looks something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 form1 = new Form1();
            Application.ThreadException += new ThreadExceptionEventHandler(form1.UnhandledThreadExceptionHandler);
            Application.Run(form1);
        }
    }
}

Then make the code in Form1 look something like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        public void UnhandledThreadExceptionHandler(object sender, ThreadExceptionEventArgs e) {
            this.HandleUnhandledException(e.Exception);
        }

        public void HandleUnhandledException(Exception e) {
            // do what you want here.
            if (MessageBox.Show("An unexpected error has occurred. Continue?",
                "My application", MessageBoxButtons.YesNo, MessageBoxIcon.Stop,
                MessageBoxDefaultButton.Button2) == DialogResult.No) {
                Application.Exit();
            }
        }

        private void button1_Click(object sender, EventArgs e) {
            throw new ApplicationException("Exception");
        }

    }
}

(Add button1 to the form and attach it button1_Click.)

Sam Meldrum