views:

1378

answers:

6

I have a winforms application.Winforms start with Program.cs where we have main() defined.I have put this code in try-catch block.

 [STAThread]
    static void Main()
    {
        try
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new frmSplash());
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            if (ex.InnerException != null)
            {
                MessageBox.Show(ex.InnerException.ToString());
            }
        }
    }

Whenever there is a win32 exception,this mechanism fails and unhandled exception message is thrown and application crashes.
I have 2 questions regarding this code:

1) Why win32 exceptions are not caught.

2) Is it a good practice to catch exceptions at the highest level.

A: 

You may need to catch as Win32Exception (or ExternalException) instead

http://msdn.microsoft.com/en-us/library/system.componentmodel.win32exception.aspx

I seem to remember that Win32Exception inherits from ExternalException but ExternalException does not inherit from Exception so won't be caught by your code.

Edit: See other answers for why this is wrong!

Edit 2: As for the second part, as stated by AnthonyWJones It is good manners to let the user know that a problem has caused the application to close, however I would recommend using a plain English statement to the user, and logging the exception stack to a log file for your own use.

Frozenskys
Both of these are Derived from Exception, hence on the surface of it the catch in the question should work. For why it isn't see my answer.
AnthonyWJones
+2  A: 

The execution of Application.Run is not throwing an error. That is happening on another thread (or at least asynchronously).

Its good idea to inform the user in friendly way that the application has failed before it disapears completely, however its not a good idea to just catch then continue.

AnthonyWJones
+6  A: 

EDIT : as Pratik pointed out, the following answer applies to .NET 1.0 and .NET 1.1 only. Starting with .NET 2.0, non-CLS exception should be caught as a RuntimeWrappedException.


Because Win32 exceptions do not derive from the .NET Exception class. Try :

try {
} catch (Exception ex) {
    // .NET exception
} catch {
    // native exception
}

See Catch non-CLSCompliant exceptions in general handlers for more information.

Mac
This is not required in .Net 2.0 by default. All non CLS exception are rapped as a RuntimeWrappedException. See http://msdn.microsoft.com/en-us/library/ms404228.aspx
Pratik
Win32Exception < ExternalException < SystemException < Exception
Tommy Carlier
@Pratik : thanks for the link.@Tommy Carlier : cf. Pratik's link...
Mac
+3  A: 

While I don't know why your catch block doesn't work try using the Application ThreadException Event. This should catch any error in application threads. Add an event handler before calling Application.Run.

For your second answer definitely yes. I develop and maintain a enterprise winforms application that talk with a web service backend on background threads. If any webservice call crashes handle the application threadexception (and also appdomain unhandledexception) event, log and popup an error that business users can report and allow them to continue without crashing the application.

Pratik
A: 

1) Win32 exceptions should be caught. Maybe the exception is being thrown from a background thread or the GC thread?

2) It depends on your app structure. For example, if your error notification UI was tied to the main form somehow (e.g. you need to invoke the UI thread from a worker thread), then it would be silly to display a UI in a code block outside the code that runs the message loop. However, if your code example is single-threaded then it would be fine.

Christian Hayter
+1  A: 

Try subscribing to these events before your application starts (Application.Run) :

You could then get rid of your try catch block.


I think it is bad practice to catch exceptions at the highest level, but you cannot avoid it ! During development (Debug), those exceptions should not be caught and the application should do the nastiest thing possible (crash ?). In production (Release), you will want your application to degrade as nicely as possible even when unhandled exceptions occur. This is one of the few uses I found for the DEBUG preprocessor variable.

Mac
There you go : 2 answers in one. Which one are you going to for (or against) ?
Mac