Runtime exception catching different between inside and outside of MSVS - c#

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?

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:
AppDomain.UnhandledException
Application.ThreadException
please read/note the docs (the first one should do) - there are some caveats.

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");
}

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.

Related

Is there a way to show an MessageBox on any exception? [duplicate]

Up until now, I just put a try/catch block around the Application.Run in the Program.cs entry point to the program. This catches all exceptions well enough in Debug mode, but when I run the program without the debug mode, exceptions don't get handled anymore. I get the unhandled exception box.
I don't want this to happen. I want all exceptions to be caught when running in non-debug mode. The program has multiple threads and preferably all exceptions from them get caught by the same handler; I want to log exceptions in the DB. Does anyone have any advice in how to do this?
Take a look at the example from the ThreadException documentation:
public static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new
ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
// 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);
}
You might also want to not catch exceptions when debugging, as this makes it easier to debug. It is somewhat of a hack, but for that you can wrap the above code around with
if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }
To prevent catching the exceptions when debugging.
EDIT: An alternate way to check for your application running inside a debugger that feels cleaner than checking a filename.
(see comments by moltenform, Kiquenet and Doug)
if(!System.Diagnostics.Debugger.IsAttached) { ... }
This avoids the problem of using a different debugger than vshost.exe.
In NET 4, certain exceptions are no longer caught by default; these tend to be exceptions that indicate a (possibly fatal) corrupted state of the executable, such as an AccessViolationException.
Try using the [HandleProcessCorruptedStateExceptions] tag in front of your main method, e.g.
using System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions
[HandleProcessCorruptedStateExceptions]
public static int Main()
{
try
{
// Catch any exceptions leaking out of the program
CallMainProgramLoop();
}
catch (Exception e) // We could be catching anything here
{
System.Console.WriteLine(e.Message);
return 1;
}
return 0;
}
A nice example can be found at http://www.csharp-examples.net/catching-unhandled-exceptions/
Basically, change your main to:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
}
You can use NBug library for that. With minimal setup like this:
NBug.Settings.Destination1 = "Type=Mail;From=me#mycompany.com;To=bugtracker#mycompany.com;SmtpServer=smtp.mycompany.com;";
AppDomain.CurrentDomain.UnhandledException += NBug.Handler.UnhandledException;
Application.ThreadException += NBug.Handler.ThreadException;
You can start collecting information on all unhandled bugs in your application, even when it's deployed to the clients. If you don't want to use a 3rd party library, you should attach to below events:
// These two should come before enabling visual styles or running the application
AppDomain.CurrentDomain.UnhandledException += ...
Application.ThreadException += ...
...
Application.Run(new Form1());

Should UnhandledException notify all unhandled exceptions? [duplicate]

I wanted to set some handler for all the unexpected exceptions that I might not have caught inside my code. In Program.Main() I used the following code:
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(ErrorHandler.HandleException);
But it didn't work as I expected. When I started the application in debugging mode and threw an exception it did call the handler, but afterwards the exception helper in Visual Studio popped up as if the exception occurred without any handling. I tried Application.Exit() inside the handler but it didn't work as well.
What I would like to achieve is that the exception is handled with my handler and then the application closes nicely. Is there any other way to do it or am I using the code above in the wrong way?
Normally I use something like this to try and catch all unexpected top-level exceptions.
using System;
static class Program
{
[STAThread]
static void Main(string[] argv)
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender,e)
=> FatalExceptionObject(e.ExceptionObject);
Application.ThreadException += (sender,e)
=> FatalExceptionHandler.Handle(e.Exception);
// whatever you need/want here
Application.Run(new MainWindow());
}
catch (Exception huh)
{
FatalExceptionHandler.Handle(huh);
}
}
static void FatalExceptionObject(object exceptionObject) {
var huh = exceptionObject as Exception;
if (huh == null) {
huh = new NotSupportedException(
"Unhandled exception doesn't derive from System.Exception: "
+ exceptionObject.ToString()
);
}
FatalExceptionHandler.Handle(huh);
}
}
Maybe it is something you find helpful too? This main code routes all three ways of catching unexpected top-level exceptions through one method call. All you now need is a static class FatalExceptionHandler that includes your top-level exception handling in its Handle method.
And really, any application developer knows there are really just two things to do there:
Show/log the exception like you see fit
Make sure you exit/kill the application process
If you think item two is strange, remember that we only bother to do this in the first place for really exceptional situations. These things are probably bugs that need changes to your application to be accurately addressed. Any other exception handling - the functional kind - should be lower down inside your actual program code, catching specific kinds of exceptions where this makes sense and handling them there in the way that makes sense. Anything else should bubble up to your FatalExceptionHandler to make itself known and stop the possibly crippled program from working from corrupted state
Dead programs tell no lies... ;-)
It's because you're running it through Visual Studio in Debug mode. If you release and install your app somewhere else, nothing but your global exception handler will be processed.
Note that unhandled exceptions are still pretty fatal; you can only really use this for logging, or maybe some hasty close-down. Neither this nor Application.ThreadException can be used as a global sink for errors.
The better approach is to add proper handling - for example, around your entire Main() logic. Note that even this can't catch a few exceptions, such as errors during form-load (which get particularly nasty - you can catch them with a debugger attached, but not without).
Perhaps what you're looking for is Environment.Exit(int errorcode)
That behavior is by design.
But there is a work-around.
Either you call Process.GetCurrentProcess().Kill(); within the handler, or simply do not let the handler end.
Check out the example:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
This should not be a default sink for exceptions, surely.
But this should be done to report exceptions gracefully.
Note: if you're application is a Windows Forms application, don't forget to:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
... or else the application will terminate, even if you handle the exceptions with the handlers specified by the other answers.

How can I make something that catches all 'unhandled' exceptions in a WinForms application?

Up until now, I just put a try/catch block around the Application.Run in the Program.cs entry point to the program. This catches all exceptions well enough in Debug mode, but when I run the program without the debug mode, exceptions don't get handled anymore. I get the unhandled exception box.
I don't want this to happen. I want all exceptions to be caught when running in non-debug mode. The program has multiple threads and preferably all exceptions from them get caught by the same handler; I want to log exceptions in the DB. Does anyone have any advice in how to do this?
Take a look at the example from the ThreadException documentation:
public static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new
ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);
// 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);
}
You might also want to not catch exceptions when debugging, as this makes it easier to debug. It is somewhat of a hack, but for that you can wrap the above code around with
if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }
To prevent catching the exceptions when debugging.
EDIT: An alternate way to check for your application running inside a debugger that feels cleaner than checking a filename.
(see comments by moltenform, Kiquenet and Doug)
if(!System.Diagnostics.Debugger.IsAttached) { ... }
This avoids the problem of using a different debugger than vshost.exe.
In NET 4, certain exceptions are no longer caught by default; these tend to be exceptions that indicate a (possibly fatal) corrupted state of the executable, such as an AccessViolationException.
Try using the [HandleProcessCorruptedStateExceptions] tag in front of your main method, e.g.
using System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions
[HandleProcessCorruptedStateExceptions]
public static int Main()
{
try
{
// Catch any exceptions leaking out of the program
CallMainProgramLoop();
}
catch (Exception e) // We could be catching anything here
{
System.Console.WriteLine(e.Message);
return 1;
}
return 0;
}
A nice example can be found at http://www.csharp-examples.net/catching-unhandled-exceptions/
Basically, change your main to:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
}
You can use NBug library for that. With minimal setup like this:
NBug.Settings.Destination1 = "Type=Mail;From=me#mycompany.com;To=bugtracker#mycompany.com;SmtpServer=smtp.mycompany.com;";
AppDomain.CurrentDomain.UnhandledException += NBug.Handler.UnhandledException;
Application.ThreadException += NBug.Handler.ThreadException;
You can start collecting information on all unhandled bugs in your application, even when it's deployed to the clients. If you don't want to use a 3rd party library, you should attach to below events:
// These two should come before enabling visual styles or running the application
AppDomain.CurrentDomain.UnhandledException += ...
Application.ThreadException += ...
...
Application.Run(new Form1());

Show form when exception occurs C#

I have been looking at the Windows API Code Pack 1.1 and have seen a Error sample and would like to integrate it into my Application, the main idea would be for it to show if any error in the application happens, well not any but some that I choose.
How can I program this?
I am using WPF
Thanks
In the constructor of your App class add:
DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
then add a method to the App class similar to the following:
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
if (MessageBox.Show("An unexpected error has occurred. You should exit this program as soon as possible.\n\n" +
"Exit the program now?\n\nError details:\n" + e.Exception.Message,
"Unexpected error", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
Shutdown();
}
You can have an catch block at the top-level of your program that will display the form with relevant error details. Or you can trap unhandled exceptions using the Application.UnhandledException (assuming you are using winforms), Application.ThreadException and AppDomain.UnhandledException.
If you want a message window to show up when any exception occurs, handled or not, then you will either have to explicitly write code in each catch block to show the form, or use something like PostSharp to weave in code that shows the form whenever an exception is thrown.
The following will catch all exceptions and display them in a messagebox:
[STAThread]
public static void Main()
{
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.Run(new Form1());
}
private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
// work with exception
MessageBox.Show(e.Exception.Message);
}
Do note that if you're heavy into threading, you might want to test its behaviour with a thread-heavy application.
More information here.

Catching exception in Main() method

Consider the following simple application: a windows form created by a "new C# windows application" sequence in VS that was modified in a following way:
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("An unexpected exception was caught.");
}
}
Form1.cs contains the following modifications:
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Error");
}
If I press F5 in IDE, then, as I expect, I see a message box saying that exception was caught and the application quits.
If I go to Debug(or Release)/bin and launch the executable, I see the standard "Unhandled exception" window, meaning that my exception handler doesn't work.
Obviously, that has something to do with exception being thrown from a different thread that Application.Run is called from. But the question remains - why the behavior differs depending on whether the application has been run from IDE or from command line?
What is the best practice to ensure that no exceptions remain unhandled in the application?
Normally Application.ThreadException will handle the exception in the Load event. You'll get the ThreadExceptionDialog that offers the Quit and Continue options.
But not when a debugger is attached. The catch clause in the message loop that displays the dialog is intentionally disabled in that case. That's necessary because it would be very difficult to trouble-shoot exceptions if that dialog pops up when you debug a program. Which this catcher no longer active, your catch clause in the Main() method now gets a shot at the exception.
You can make it consistent by using Application.SetUnhandledExceptionMode() in the Main() method. You shouldn't, exceptions really are hard to debug if you do this. If you want to customize exception handling for the UI thread then you should register your own Application.ThreadException handler:
if (!System.Diagnostics.Debugger.IsAttached)
Application.ThreadException += myThreadException;
Trapping unhandled exceptions in worker threads requires a AppDomain.UnhandledException handler. They are not recoverable.
Also beware of a bug in 64-bit Windows, exceptions in the Load event are swallowed without diagnostic when a debugger is attached. Force AnyCPU mode to avoid that trap.
In addition to catching any exceptions thrown inside the Main method you must also handle AppDomain.CurrentDomain.UnhandledException and Application.ThreadException.
Not sure why the behavior differs with and without a debugger attached though.

Categories