5

I am calling the following function some where in program that will throw an exception

public static List<Templates> LoadTemplates()
{
    // ...
    // System.Threading.Thread.CurrentThread.ManagedThreadId == 1 // ID written to log file
    System.IO.Directory.GetFiles("does_not_exist_directory");
    // ...
}

And I try to catch the exception in the default Program.cs

try
{
    // System.Threading.Thread.CurrentThread.ManagedThreadId == 1
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}
catch (Exception ex)
{
    MessageBox.Show("ERROR CAUGHT");
}
finally { // do clean up }

When run in MSVS, the exception get caught as expected. But when run by double-clicking the .exe in the output directory the exception display in a message dialog stating

EDIT:

To catch the error when running the .exe from output directory, the code must be compiled with handling the Application.ThreadException event

Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.Run(new Form());

But then MSVS will behave undesirably by showing the MSVS native "Troubleshooting Tips" borderless message dialog "Unhandled Exception".

How can I ensure that it behaves the same in and out of MSVS?

Jake
  • 11,273
  • 21
  • 90
  • 147
  • It's actually quite frustrating when I cannot see the reason for up votes against my post especially when i suppose you guys will not be able to reproduce my problem. =( – Jake Sep 29 '11 at 09:27
  • possible duplicate of [What's the difference between Application.ThreadException and AppDomain.CurrentDomain.UnhandledException?](http://stackoverflow.com/questions/2014562/whats-the-difference-between-application-threadexception-and-appdomain-currentdo) – Hans Passant Sep 30 '11 at 03:23

3 Answers3

4

The code you have shown will only catch exceptions in the same thread. It's really hard to tell without seeing the offending code and it's context.

You can subscribe to a couple of events to catch all of those:

please read/note the docs (the first one should do) - there are some caveats.

Random Dev
  • 51,810
  • 9
  • 92
  • 119
  • I seriously do not think the code is running in another thread unless static singleton + static class method call results in some kind of threaded call? Or calling up another Form which in turns call this LoadTemplate also equals to threaded call? – Jake Sep 29 '11 at 06:58
0

It looks like your LoadTemplates call is made in an own Thread. I assume you don't see the MessageBox in Debug mode. You will see the Visual Studio exception window.

To solve this problem try to use the AppDomain.CurrentDomain.UnhandledException event:

[STAThread]
static void Main() {
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
    MessageBox.Show("Unhandled exception");
}
dwonisch
  • 5,595
  • 2
  • 30
  • 43
  • I think this does not work. The said dialog does not appear now when run in MSVS. But the exception is still unhandled with the MSVS native exception-breakpoint Troubleshooting Tips box with the title "DirectoryNotFoundException was unhandled by user code" – Jake Sep 29 '11 at 06:56
  • Is the exception caught when you use a catch block without exception specified? `try{...} catch {...}` – dwonisch Sep 29 '11 at 07:05
  • The exception is caught with try/catch in MSVS run (F5 start debugging), with or without "Exception e" arguments. – Jake Sep 29 '11 at 07:24
  • The exception seems to be caught by Application.Run(). Can you catch it when adding `Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);` before `Application.Run()` – dwonisch Sep 29 '11 at 08:07
  • you could even call woni's suggested line from static code to increase your chances of catching the exception in your debugger – mtijn Sep 29 '11 at 08:54
  • @woni I can catch it in Application.ThreadException event. But when MSVS behave differently than normal running of the application. Is there a method that works the same whether run in MSVS or in output drectory? – Jake Sep 30 '11 at 03:15
  • You can run it without debugging in Visual Studio (Ctrl + F5). You can also try with this line, instead of CatchException. `Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)` – dwonisch Sep 30 '11 at 07:24
0

Pertaining to the behaviour of exceptions in and out of MSVS, Carsten was right to point me to the code in MSDN but woni helped me realise the situation better.

(It might be otherwise, but) It appears that MSVS hooks its internal event handler to the application when it is run from inside MSVS and that handler is run before my handler in the application. Hence when a unhandled exception occurs, MSVS will show its native "troubleshooting tips" dialog box pointing to the error line.

At this point, if I click continue (F5) to continue execute the code, MSVS will re-throw the exception and this time it will be caught by my own handlers.

Outside of MSVS, no other handlers are subscribed so it just runs my handlers directly.

Jake
  • 11,273
  • 21
  • 90
  • 147