5

Possible Duplicate:
Exception handling problem in release mode

I suspect there is a perfectly simple explanation for this, but I can't seem to find it.

When my WinForms C# 4.0 application loads itself in the Program.cs file, the entire Main() function has inside it a try/catch statement.

I have written a little exception wrapper which behaves quite similarly to the vanilla .net "uncaught exception" box, except it provides a bit more information, allows the exception tree to be saved (serialised), and it allows the user to submit the error report directly to me.

Now, it works fine while debugging (F5). If I trigger an exception anywhere in the program which is in the main thread, if there is not try/catch then the exception fires its way all the way back to Main() and shows the custom window.

(All other exceptions I have accounted for and are handled appropriately).

When I run the program simply by running the .exe file, the vanilla .net exception box comes up, not the one I have coded.

Is there any reason you can think of why this would happen? The strangest thing is that it behaves quite differently when running in debug mode vs running on its own. I am building as debug - not release.

Edit (22-March-11):

I'm just adding a little addendum here, in case some of you can't find the answer hidden in the comments for the accepted answer below: Forget that I said I was building as debug instead of release. That is of no relevance - I just added it for extra info. What is important is that when I'm debugging in VS the exceptions are caught as expected, but when executing my EXE outside VS they aren't.

As Cody said, Application.Run() has its own handler for exceptions which is why they never get to my main catch, however I mentioned that I am not even using Application.Run() anywhere in my code... instead my GUI is first launched with Form.ShowDialog().

I have done some experimentation, and can confirm that Form.ShowDialog() behaves the same was as Application.Run() in that exceptions are handled within the method itself.

Community
  • 1
  • 1
Ozzah
  • 10,631
  • 16
  • 77
  • 116
  • 1
    Are you sure its your handler-code that doesnt generate the "unpretty" exception box? – stefan Feb 25 '11 at 04:54
  • @Cody Gray, Can I just confirm with you: I am have no calls to `Application.Run` anywhere in my code. The thread you marked mine as being a duplicate of, and your answer to my question here, both say that the generic .Net error box is generated by the internal event handler of `Application.Run`. This seems to conflict with my source code. (?) – Ozzah Feb 28 '11 at 01:43
  • See my answer to your comment on my answer (whoah, did that make sense?). If that's the case, it might seem that this isn't an "exact duplicate", but we didn't have any way of knowing that since you didn't *post* your source code. Always a reason why it's a good idea to include the applicable sections of your code in the question. Since we're called on so often to do psychic debugging, we sometimes trust our instincts more than we sometimes should. – Cody Gray - on strike Feb 28 '11 at 04:28

1 Answers1

6

This is the expected behavior.

The difference you see is a result of the application being run with the debugger attached. When you launch it from within Visual Studio, the debugger is automatically attached (unless, of course, you choose to "Start Without Debugging"). That disables the built-in exception handler, which is the one responsible for showing you the "vanilla" .NET exception dialog. Launching it from outside VS doesn't attach the debugger, leaving the built-in exception handling enabled. (Note that this has nothing to do with compiling your program in "Debug" mode versus "Release" mode.)

See the accepted answer to this related question for more information. I do not believe the difference between VB.NET and C# is relevant in this case.

As that answer mentions, there is a way to disable the built-in exception handler. But before choosing to do so, I recommend reconsidering your approach. Rather than wrapping your entire Main method in a try-catch block, which sounds like a bit of a code smell to me, you might consider handling the built-in AppDomain.UnhandledException event. Jeff Atwood posted a great article here on Code Project about how to replace the standard .NET exception handling with your own more user-friendly method. The solution he proposes has become only that much more elegant as later versions of the .NET FW have improved how the AppDomain.UnhandledException event is handled.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • I think you have miss-read the question. – Justin Feb 25 '11 at 05:39
  • @Kragen: Why is that? Maybe so; can you clarify what I've misread? I'll be happy to modify/remove my answer accordingly. – Cody Gray - on strike Feb 25 '11 at 05:40
  • @Cody When run in the debugger the application is displaying a custom exception dialog, which would indicate that there are no exceptions left completely unhandled and so the default exception handler should never appear. – Justin Feb 25 '11 at 05:52
  • @Kragen: That's the way I read the question, too. The difference lies in whether the exception handler built into the `Application.Run` method is enabled or not. When you're running under the debugger, it's disabled, so the try-catch block surrounding the `Main` method is handling the exception. When you're *not* running under the debugger, the built-in exception handling takes over and displays the dialog before the exception ever gets passed up the stack to your `Main` method's try-catch block. – Cody Gray - on strike Feb 25 '11 at 05:55
  • @Cody Ah - I hadn't appredicated that the unhandled exception was handled **inside** of the `Application.Run`, or that this behaviour was completely disabled if a debugger is attached. For some reason I always though that unhandled exceptions were thrown by `Application.Run`, although thinking about it I realise how absurd that would be! – Justin Feb 25 '11 at 07:11
  • @Cody: Forgive me for hijacking this question a bit . . . Application.Run has it's own exception handler, so when it is wrapped in a try/catch block, it handles the exception and therefore that try/catch will never get an exception to handle. Is that correct? Also, why does Application.Run have it's own exception handler? – richard Feb 25 '11 at 07:38
  • @Richard: Yes, that about sums up what's going on here. Have you read Hans Passant's answer to the duplicate question that I linked to? It provides a more comprehensive explanation than I did here. Presumably, `Application.Run` has its own exception handler *precisely* to show the "unhandled exception" dialog that the asker is complaining about here. Otherwise, your application would just crash without giving the user a chance to "continue". The way I see it, that's one of the big advantages of managed code. You have the ability to override it if you wish, but you don't have to. – Cody Gray - on strike Feb 25 '11 at 07:40
  • @Cody: I did. But maybe I'm missing something - it looks like his answer is short and not as comprehensive as yours. lol On a side note, I got around this using this in my `Main` - `Application.ThreadException += new ThreadExceptionEventHandler(HandleError);` where `HandleError` was my method to log and email me about the error. Is this an acceptable way to do it as well? – richard Feb 25 '11 at 07:45
  • @Richard: Perhaps; I'm not sure what you're still missing so I'm not sure what else I can clarify. Yeah, that looks like an acceptable way of doing things. The latter portion of my answer suggests doing something similar with the `AppDomain.UnhandledException` event. The only real advantage of that over `Application.ThreadException` is that the latter only handles exceptions on the single application thread. The [documentation](http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx) has a better explanation under the "Other Events for Unhandled Exceptions" heading. – Cody Gray - on strike Feb 25 '11 at 07:51
  • I'm just saying maybe I'm missing something in regard to Hans Passat's answer, because you said it looked more comprehensive, and when I looked, it was shorter and I thought yours was more comprehensive. That's all. I understand this issue now though. Thanks for your help. :-) – richard Feb 25 '11 at 07:55
  • I'd like to butt in here. I'm not actually using `Application.Run`, my Main() method has the try/catch, inside which is some basic construction and a `Form.ShowDialog` which basically starts the workflow GUI. I'm fairly certain I haven't used `Application.Run` anywhere in my program, but I appreciate what you said about try/catch blocks. I've read the thread you linked to and will change my code around. Nevertheless, in light of me not using `Application.Run`, do you have a new answer as to why I'm not seeing my custom error reporting form? – Ozzah Feb 27 '11 at 22:06
  • @Ozzah: My best guess would be that something similar is happening inside the message pump that `ShowDialog` creates. The reason you can get away with not using `Application.Run` to create the Windows message pump is because a modal dialog has its own message pump that you're using instead. I haven't done enough testing to be able to say for sure, but I'd imagine that Microsoft has done something similar there as well. The point is that they want their exception-handler dialog to show up without the developer having to do anything. You want to override that, so you have to work harder. – Cody Gray - on strike Feb 28 '11 at 04:26