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.
Related
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());
Currently, when there is an unhandled error in one of the forms in my Windows Forms program, a dialog pops up with lots of details which are irrelevant and confusing to the end user.
I would like to replace that dialog with a more user-friendly dialog (and use a Tabbed interface to hide but make available technical details) whenever an unhandled error occurs in one of my forms.
Is there a way to replace this default dialog with a custom one?
My application is an MDI one, so if an error occurs in a form, I would like to just close out that form, show the error in a friendly way and allow them to work with other windows in the application (unless its a critical error).
A couple of ways spring to mind. Easiest one is to catch all unhandled exceptions by listening to the Application.ThreadException event
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message);
}
However that would simply stop the crashing and not close the mdi form. If you stop the sending thread, it would stop the mdi form altogether (it's easier outside mdi, then the forms can run in separate threads which can be initiated sandboxed).
What I normally do is run all code sandboxed. Normally encapsulated inside an action object, but i could be a simple procedure e.g.
public static bool Run(Action a)
{
try
{
a();
return true;
}
catch(Exception ex)
{
//custom error handling here
return false;
}
}
example call:
private void button1_Click(object sender, EventArgs e)
{
Run( ()=>throw new Exception());
}
Running in a standard method has the added benefit of being able to control things as a wait cursor or logging. If it wasn't an mdi environment, there would be some alternatives, but hope this one is doable.
Global meaning "in one place" e.g. not multiple try...catches e.g. on each event handler. Proven meaning "known to work" - I'm aware covering both .NET and other exceptions is not straightforward.
Thanks.
Solution coded from answers below.
Note: this is believed to cover exceptions from additional threads.
static class Program
{
static void MyHandler(Exception e)
{ MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
static void MyThreadExceptionEventHandler(object sender, ThreadExceptionEventArgs args)
{ MyHandler(args.Exception);
// App continues.
}
static void MyAppExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{ MyHandler((Exception)args.ExceptionObject);
// There follows a OS "needs to close" dialog, terminating app.
}
static void Main()
{
// For UI thread exceptions
Application.ThreadException +=
new ThreadExceptionEventHandler(MyThreadExceptionEventHandler);
// Force all Windows Forms errors to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// For non-UI thread exceptions
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(MyAppExceptionHandler);
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
The default behavior when it displays error dialog on unhandled exception and terminates is a good formula. If you don't like the look and feel of this dialog you can show your own instead but the principle is the same (good example is here):
public static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException
+= new ThreadExceptionEventHandler(/* YOUR OWN HANDLER */);
// 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(/* YOUR OWN HANDLER */);
// Runs the application.
Application.Run(new /* YOUR MAIN FORM*/);
}
Generally there is no magic 'solution' to exception handling - you have to think about handling specific exceptions before calling any method. There is nothing special about Windows Forms in this regard.
Handle the AppDomain.CurrentDomain.UnhandledException and the Application.ThreadException you should be good!
Use Exception Handling Application Block and exception policy that may be adjusted in config file. I like it but it might be 'too heavy' for someone when considering very small projects.
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());
How to track window form crashing ? Like any event is called or anything else is called or we can track that window form is crashed ? Like dispose is called window form is crashed. But anything else which is happened so we can track out crashing of window form ?
Like problem is I have one window application on that there is tutorial balloon on the main form which moves for each control on the main form and describes the application functionality by indicating control on the main form one by one. And each time balloon moves balloon is disposes and new balloon form is created.
Now I want to insert the step number in the database when that balloon was crashed. I cannot understand what should I do ? What is happened when that balloon window(window form) is crashed ? There is a dispose event which is occurred but it is happened each time balloon creates so is there any thing else to track crashing ?
EDIT: Sorry to all, I forgot to specify that it is with .net framework 2.0.
Use this: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx
If any undhandled exception occurs in a forms thread, it will get here. If it's null, you get the usual dialog (undhandled exception occurred, you can continue or close, and see the stack trace).
This is an excerpt from a small Windows Forms 2.0 program of mine:
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException +=
applicationThreadException;
// Set the unhandled exception mode to force all Windows Forms
// errors to go through our handler.
Application.SetUnhandledExceptionMode(
UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException +=
currentDomainUnhandledException;
...
}
With the two handlers
private static void currentDomainUnhandledException(
object sender,
UnhandledExceptionEventArgs e)
{
handleException(e.ExceptionObject as Exception);
}
and
private static void applicationThreadException(
object sender,
ThreadExceptionEventArgs e)
{
handleException(e.Exception);
}
The actual function to handle the exceptions does in my example:
private static void handleException(
Exception exception)
{
LogCentral.Current.LogError(
#"Exception occurred.",
exception);
if (ErrorForm.IsErrorFormShowing)
{
LogCentral.Current.LogInfo(
#"Error form already showing, not showing again.",
exception);
}
else
{
using (var form = new ErrorForm(exception))
{
var result = form.ShowDialog();
if (result == DialogResult.Abort)
{
Application.Exit();
}
}
}
}
I.e. it logs the error via log4net and then displays an error form to show the user further information (exception message) and allow to quit the application.
In your Program.cs file, place a try/catch block inside the Main() function. The idea is to have the Application.Run(yourformhere) inside such a block. Then inside the catch you can probably manage to save some state (like the step at which the balloon crashed the form) in the DB. Good Luck!