views:

76

answers:

2

I use this code to catch the WinForm application UnhandledException.

[STAThread]
static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new
      System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

    // 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 += 
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    try
    {
        Application.Run(new MainForm());
    } catch....

There I will try to restart the application. Now my problem is to simulate a exception like this. I tried before try (in main): throw new NullReferenceException("test"); VS caught it.

Tried also in MainForm code with button :

    private void button1_Click(object sender, EventArgs ev)
    {         
        ThreadPool.QueueUserWorkItem(new WaitCallback(TestMe), null);
    }

    protected void TestMe(object state)
    {
        string s = state.ToString();
    }

did not help, VS caught it, even in Release mode.

  • How should I, finally, force the application generate UnhandleldException?
  • Will I be able to restart the application in CurrentDomain_UnhandledException?
  • How can I generate a ThreadException?

PS.

If I launch outside the VS a windows generic window

Application MyApplication" encountered a error and should be closed...blabla...Send report/Don't send.

I want, however, VS enter this method (...Domain_Unhahdled...)

EDIT: When restarting the application, Is it possible to disable the windows crash message appearing like: alt text ?

Code:

static void CurrentDomain_UnhandledException(object sender, 
    UnhandledExceptionEventArgs e)
{
    // Since we can't prevent the app from terminating
    // log this to the event log.
    Logger.LogMessage(ERROR, errorMsg);
    Application.Restart();
A: 

Visual Studio may be set to break on exceptions, but if you continue stepping through the code, it should still follow your desired path. You should also try running the app outside of VS.

Restarting the application after an unhandled exception is a bad idea because you're (by definition) in an unknown state. Restarting, if even possible, may put you in a never-ending loop of restarting if the exception condition is never changed. Instead, consider trying to log the exception information to a web server so you can investigate and fix crashes. Be sure to get the user's permission before uploading the crash data though.

C. Dragon 76
My application can be restarted, because I do periodically some actions. Even if one of them fails, is preferable that other continues. If I am on the exception, I can't continue stepping.
serhio
A: 

I'm still not completely sure I understand the question, but a few things to mention:

  • Application.ThreadException and Application.SetUnhandledExceptionMode only apply to Windows Forms threads. Arbitrary ThreadPool threads are not actually Windows Forms threads, even in a Winforms app, so those two lines of code are ineffective.

  • Registering an event with AppDomain.CurrentDomain.UnhandledException will trap exceptions occurring on ThreadPool threads.

  • However, the UnhandledException event cannot actually handle an exception. By that time it's too late to stop the process from terminating, which will always happen if an exception occurs on a background thread (unless you've enabled the legacy .NET 1.1 behavior, but... don't.) This event is really only good for logging or cleanup.

I've tested this myself using test code similar to yours and verified that the code inside the exception "handler" does execute. But the app will still crash, and you can't stop it.

Update: I'm going to make one more attempt at this, and that's it.

If your aim is to have an unattended application running at all times, you have precisely three options:

  1. Handle your exceptions properly. This is, by far, the best and probably only correct solution. Hooking AppDomain.UnhandledException is not handling the exception. By the time control enters that event handler, your application has already crashed. You can't save it anymore.

    An unhandled exception escaping from a background thread is a catastrophic bug in your code that you need to fix. An unhandled exception escaping from a background thread is a catastrophic bug in your code that you need to fix. An unhandled exception escaping from a background thread is a catastrophic bug in your code that you need to fix. Please, no more comments to the effect of "I don't care" - you need to start caring.

  2. Ask Windows politely to restart the application for you. Unlike attempting the restart from a crash handler, which is an incredibly bad idea for reasons too numerous to fully enumerate (data corruption, infinite restart loops, resource leaks, OS instability, etc.), registering for a restart actually allows this to happen in a semi-controlled fashion. As I mentioned in the comments, it's straightforward to interop with this API in .NET. You register for this as soon as the application starts, not when it crashes and your app is in an untrusted state.

  3. Create a supervisor service that watches your application and restarts it if it crashes. This is still bad for many of the reasons discussed in the previous two points, but you at least have a fighting chance at some level of stability.

    You can get a pretty reliable indication of an application crash by using a named mutex, waiting on that in your supervisor, and watching for the WAIT_ABANDONED state (AbandonedMutexException in .NET). The abandoned state only occurs when the process that owns a mutex terminates without releasing it - i.e. has an unhandled exception. And with a little bit more interop hacking, you can also detect and close the crash window.

Those are your options. I strongly suggest that you handle exceptions on background threads, because an unhandled exception escaping from a background thread is a catastrophic bug in your code that you need to fix. If it's coming from an external component and you can't catch it, then the catastrophic bug is in that component and you should consider reporting it to the author or using a different component.

Simply having a requirement that says "this application must run at all times and should totally ignore fatal crashes" doesn't make that scenario possible if the app isn't stable enough to actually keep running. A crash is a crash. You don't design a car to just restart itself immediately if the engine suddenly dies. The best you can do is ask a trusted operator, whether that's a human operator, operating system or some supervisory software - to restart the application on its behalf.

Variations of this question seem to come up so often - basically, "My app should never crash, or if it does, it should be invisible. I want to eat every unhandled exception and pretend it didn't happen." Not only is that impossible but it runs counter to virtually every principle of good design (especially the "fail fast" principle, which can certainly be re-interpreted but should never be ignored entirely).

That's all I can say. If you're unwilling to accept any of it then good luck finding a viable alternative.

Aaronaught
Application.ThreadException have almost nothing to to with threads, but with Windows events (like Click etc.) For the others, I could agree, but, finally, how can I make VS to enter my "handler" method, this was the question.
serhio
@serhio: I know, that's what I'm saying, there's no point in showing the code for those two events, they're not relevant here. What I've said is that VS **does** enter the event handler, so if it's not doing it in your case then you need to post steps to reproduce.
Aaronaught
And no, it is absolutely **not** possible to prevent the Windows crash dialog from showing up and just automatically "restarting". It's as I've stated, once you get to `AppDomain.UnhandledException` **it is too late** to prevent the crash. The crash has *already happened*, it's just a way for you to do damage control or try to log something. This is starting to look like another "how can I just ignore all exceptions" question - **you can't**.
Aaronaught
@Aaronaught, I don't want to prevent the crash, I want do not display the Windows message, cause I restart my application, and the message still remains. **The user can't interact with the screen.** (By ex. my application displays to a Train Passengers screen)
serhio
@serhio: If you don't want the crash dialog to show up *then don't crash your application.* Even if you *could* swallow a full-on crash, it would be a monstrously bad idea, even worse than restarting a Winforms application in the unhandled exception event. If you absolutely need this level of isolation, if you must perform some operation that you know might "crash" but for some reason cannot afford to take your whole application down, then perform that operation in a separate process, one which doesn't have any UI. But honestly, just fix the bugs and write robust threading code.
Aaronaught
@Aaronaught: oh lala. I use a third party ActiveX that can't control. This is a web cam component. So, I don't know each bug of this AcX, but know that it can reconnect and then everything will continue OK. So, finally, I not crashing my application, but conscientiously want that the application continue working even if recieve strange COM or thread exceptions.
serhio
@serhio: If you don't control the code then you'll have to isolate that component. You cannot continue running after a *crash*. By the time you hit the `AppDomain.UnhandledException` event, you've *already crashed* - the event is just a last chance to deploy the airbags. If this ActiveX component is actually raising unhandled exceptions on background threads, then that component is hopelessly broken and you'll have to isolate it in its own AppDomain or process. Otherwise, design your app to catch the exceptions instead of letting them go unhandled.
Aaronaught
@Aaronaught: Isolate it. What should it be? I have an AcX object AxDisplay that is a wrapper of a COMDisplay. I build an object MyDisplay : AxDisplay added some features. Now in my form I have 3x3 MyDisplays. I don't know what to isolate. And don't need it. My taks is to always keep the application launched. there is a dedicated computer just for this application, and I don't care about Unhandled Exceptions, or haw bad is it.
serhio
If MyDisplay4 thrown an exception (camera has a microshutdown, network was down for a second, electrical trouble), I keep my application alive, because restarting it is a very big problem, the administrator should detect the respective computer, be present, log in, restart application etc etc. As MyDisplay will be reconnected automatically after a specified delay of time, I don't care about unhandled exceptions. DONT CARE
serhio