I am trying to implement global level error handling in my windows application
I have the button click event for the form which creates some error
label1.Text =
class1.Calculate(Convert.ToSingle(textBox1.Text), Convert.ToSingle(textBox2.Text))
.ToString(CultureInfo.InvariantCulture);
MessageBox.Show("That was really Close");
now I want the control to go to message box, the unhandled error are being handled in the main function as
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.Run(new Form1());
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
if (e.Exception.InnerException != null)
MessageBox.Show(e.Exception.InnerException.Message.ToString());
else MessageBox.Show(e.Exception.ToString());
}
This code sample does handles the exception but I want the control back to the button Click, that is The MessageBox.Show("That was really Close"); should get called after exception handling
If you don't want the method to stop on an exception then you need to handle the exception at that point. You could have the catch call some kind of global error handling method but you will need a try catch in that method.
Global level exception handling is for exceptions that you can't deal with immediately and need to catch before the program dies, usually for logging and such like.
Global level exception handling is not a substitute for handling exceptions at the correct place. If you expect code to throw an exception and it is one you can deal with then you should put a try/catch at that point of the code. In the example above you say you want to carry on running the method so clearly the error is not a fatal one so you should deal with it in the normal way.
Often though it should be noted that exceptions that you can handle are ones that can be avoided. For example checking what you pass to a method before passing it. The ones that can't be removed entirely are usually ones to do with external resources (eg reading files). I'm sure there are a lot of other exceptions but as somebody wise once said "Exceptions are for exceptional circumstances". If you can foresee them you should try to avoid them.
In this case I assume the exception is related to invalid input in your text boxes. In this case you should use Single.TryParse to verify the input before passing it on to your method. If either of the values fails to parse you can then let the user know that properly.
Related
Unexpected exceptions that should terminate execution of the program are simply thrown. They are caught by CurrentDomain_UnhandledException and taken care of there - logged if necessary, and a generic "This app is about to crash and you have nothing to do about it" message displayed to the user.
But what about those exceptions that only need to cancel an operation, while showing the user a more useful message? e.g. informing the user that a file can't be accessed because it's being used by another process. This exception might be deeply nested, and I wouldn't want to check for some flag at every method return. I'd rather have something like this: when the user initiates the most "external" method - say, a button click event handler, the code will include a try-catch block catching all DisplayToUserException's , and rethrow any other exceptions. So I'll have to create this custom exception class.
But before I go down that path, I'd like to know if that's the standard thing to do, or perhaps there's a better solution for this. Or perhaps a class already built for this. Hence this question.
It's ok to put a try/catch block around your UI events:
public void Button1_Click(object sender, EventArgs e)
{
try {
// Do something interesting, like calling methods that throw (nested) exceptions
// Maybe these methods do file I/O
}
// Though it's better to catch a more-specific exception or set of exceptions
catch (IOException ex){
MessageBox.Show(ex.ToString());
}
}
This limits the effects of the exception to the UI operation (the button click, in this case).
A truly unhandled exception, one that you can't anticipate or do anything about, will still get handled by the AppDomain exception handler.
Note also that the Message property of an exception is meant for display to the user. It's ok to catch a "technical" exception, and rethrow as an exception with a user-friendly message. But be sure to include the original exception:
try {
// Do something with the file name in the <c>path</c> variable
}
catch(IOException ex){
throw new InvalidOperationException(
String.Format("Can't perform that file I/O on {0}, sorry about that", path), ex);
}
I am working on a big application that has a lot of levels of hierarchy, and I am getting to a point where I am going nuts about calling logging messages and forgetting about them.
From time to time while testing I run into exceptions. Now I am forwarding error messages to my main form through interfaces and other ways.
Is there a way to make the application in a case of an exception to always trigger a single method in the main form.
I mean, now I catch the exception and forward it through the interfaces. I would like to be able to ignore this and every time an exception happens, execute automaticly one method in the main form
If you allow the exceptions to bubble up through the application you can use AppDomain.UnhandledException. You should allow any exception which you cannot meaningfully handle to bubble up anyway.
Something like this should do the trick:
class Program
{
public static void Main()
{
form = new MainForm();
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(form.OnUnhandledException);
Application.Run(form);
}
}
I'm working on an existing C# program that queries and makes changes to various resources outside of the program and computer that the program is run on. The program works on most computers but randomly fails on random computers every so often. When this happens we have no feedback as to why other than what the user tells us about the exception that was thrown up on the screen that they may or may not have already cleared. Even if they leave it up on the screen for us it provides little to no useful information to us. I have since modified the program to log particular events and gathered information to a text file that I can use to approximate where the program stopped. This is at least a start but from reading many threads on stackoverflow.com as well as other forums I know that the program needs to at least make an attempt to handle the specific exceptions that could come up when querying and modifying LDAP, DS, DNS, SQL and so on.
Currently there is just big try blocks surrounding all of the to do code with just one catch block at the end of each.
private void method_name()
{
try
{
//many lines of to do code calling many other methods
}
catch (exception ex)
{
MessageBox.Show("An Error has occurred in method_name() :" + ex.Message);
}
My first thought was to nest more specific try/catch blocks within the larger try blocks but I keep running into problems with variables becoming unreachable in different contexts. for example
try
{
LdapConnection ldapConn = new LdapConnection();
ldapConn.Connect(details of connection);
ldapConn.Bind(details of bind statement);
LdapSearchQueue queue = ldapConn.Search(search criteria and such);
LdapMessage message;
}
catch (somesortofexception ex)
{
//do something sensible about it
}
while ((message = queue.getResponse()) != null)
{
//do things with message
}
ldapConn.Disconnect();
the problem being that message and queue are unreachable outside of the try block. This is just one example of something done withing the "//many lines of to do code calling many other methods" that I'm trying to work with.
So here are my questions:
Would it be better to try and make the try block bigger in the above example to include the while loop and ldap disconnect or to just leave the big try loop, make a list of things that happen during that and create many catch blocks at the end to catch specific exceptions? I feel like putting in the smaller try blocks around specific code is the way to go based on what I've read on this site.
Should I use the smaller try blocks like I've been trying to implement, would be be okay to just use a catch block that catches any exception raised within that small snippet of code and log it to my log file or should I try and catch specific exceptions? I don't really have anything different I can do with those exceptions other than log them to the file anyways.
Do I need to throw the exceptions? I don't really want anything bubbling up to the user other than a message in plain english saying that something went wrong and to contact IT. Currently none of the catch blocks throw anything.
About breaking down exceptions, I would always separate the connection code from the query one.
So this would become:
LdapConnection ldapConn = new LdapConnection();
try
{
ldapConn.Connect(details of connection);
ldapConn.Bind(details of bind statement);
}
catch (somesortofexception ex)
{
//Log, send error message..
ldapConn = null;
}
if (ldapConn != null)
{
try
{
//Do what you need with your connection
}
catch (Exception ex)
{
//Log, Error....
}
finally
{
//Disconnect your ldap here
}
}
Ideally i would put all the connection code and search code in separate methods as well,
so you'll have some nicer stack trace.
About error message I would also just use some generic message and log exception specifics into some kind of file ( http://logging.apache.org/log4net/ ) is quite nice for having nicely formatted log files.
A local catch block that swallows a specific exception is fine as long as you're expecting that exception and it can be handled locally. In this case you can provide information to the user based only on what the exception contains, or you can move the variable definitions above the try block if you want to include their state in the logging and/or message.
For exceptions that you're not expecting, you should let them bubble upwards to the top of the call stack where they can be logged by a global handler before exiting the program gracefully. You don't want to potentially nail the corpse in an upright position by swallowing these exceptions.
Assuming this is a WinForms app, the setup of global handlers looks something like this:
public static void Main(string[] args)
{
// Switch-off the Windows Forms default handler for unhandled exceptions.
// NB From .NET 4 upwards, this won't work if the process state is corrupted.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Setup event handler to intercept an unhandled exception on a UI thread.
// NB The exception will still terminate the application.
// But you can show a MessageBox and/or log the exception.
Application.ThreadException +=
new ThreadExceptionEventHandler(App_UiThreadException);
// Setup event handler to intercept unhandled exception on a non-UI thread.
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(App_NonUiThreadException);
// Run the application (open main form etc).
}
i know this could be a little weird but a doubt is a doubt afterall...
what would happen in the following situation...
private void SendMail()
{
try
{
//i try to send a mail and it throws an exception
}
catch(Exception ex)
{
//so i will handle that exception over here
//and since an exception occurred while sending a mail
//i will log an event with the eventlog
//All i want to know is what if an exception occurs here
//while writing the error log, how should i handle it??
}
}
Thank you.
I would personally wrap the call to write to event log with another try\catch statement.
However, ultimately it depends on what your specification is. If it is critical to the system that the failure is written to the event log then you should allow it to be thrown. However, based on your example, I doubt this is what you want to do.
You can simply catch errors in the error logging method. However I wouldn't personally do that, as broken error logging is a sign your application can't function at all.
private void SendMail()
{
try
{
//i try to send a mail and it throws an exception
}
catch(Exception ex)
{
WriteToLog();
}
}
private void WriteToLog()
{
try
{
// Write to the Log
}
catch(Exception ex)
{
// Error Will Robinson
// You should probably make this error catching specialized instead of pokeman error handling
}
}
Each exception is caught only when inside a try-catch block. You could nest try-catch but is generally not a good idea.
You could add a try-catch block in your catch block as well.
Considering the kind of exceptions when writing to a file (rights, disk space...) I would advice not to handle it in here. If it fails the first time, there's good chance you won't be able to write to the event log that it's not possible to write in the event log...
Let it bubble up and be handled by an upper level try/catch.
Chris S. has the best answer. Placing a try-catch block inside a catch block is very rarely a good idea. and in your case it will just convolute your code. If you check to see if you were successful in writing to your log file here, you will have to do it in every place where you try to write into your log file. You can easily avoid this unnecessary code duplication by having all your individual modules be self contained when it comes to notifying/handling of error conditions within these modules. When sending your mail fails you perform the proper actions inside your catch block to handle this exceptional condition like:
disposing of the contents of your mail object
making sure your socket is closed
writing an entry into your log file to note the error
Inside your catch block just call whatever API you have defined to writing a log entry into your logfile and forget about about the rest. Inside your logging API is where you should handle any logging related exceptional cases (the disk is full, no permission to write to file, file not found, etc...). Your mailing module does not need to know if the logging was successful or not, that responsibility should be delegated to the logging module.
I personally handle this situation using a simple extension method.
public static class MyExtentions
{
public static void LogToErrorFile(this Exception exception)
{
try
{
System.IO.File.AppendAllText(System.IO.Path.Combine(Application.StartupPath, "error_log.txt"),
String.Format("{0}\tProgram Error: {1}\n", DateTime.Now, exception.ToString()));
}
catch
{
// Handle however you wish
}
}
}
The usage is simple:
try
{
...
}
catch(Exception ex)
{
ex.LogToErrorFile();
}
You can then handle the caught exception inside the extension method however you want, or simply don't catch it and let it bubble up to the top. I've found this design to be a simple, reproducible way to handle exceptions throughout the application.
Firstly I would say don't catch "Exception" in catch block. You could instead, for mailing, check for all validity and then catch specific exception(SmtpException, ) that you can do something about(and informing user with a friendly message). Throwing exception from your code and informing the UI about is not a bad idea. If your methods accepts inputs with certain specification and if they are not met, your method should/can throw error and inform user about it.
For exceptions that have no control over, use global handling exception, like Application_Error for web.
Getting Better Information on Unhandled Exceptions Peter Bromberg explains this better.
Also for any privildged resource you are accessing, like eventlogs, make sure you assembly has access to it.
Useful links Build a Really Useful ASP.NET Exception Engine By Peter A. Bromberg
and
Documenting Exceptional Developers By Peter A. Bromberg
For web application look into
Health monitoring
Exception logging
One more thing, if your application goes wrong/ throws error that can't handle( at all) its better to let it go down gracefully and not continue. Application in unstable state is not good idea.
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.