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 have been crawling the Internet for quite a long time in hope of a solution, and I've come across a number of answers, but none of these seem to achieve what I want.
I'm trying to handle exceptions without causing the app to crash. Rather than the app simply exiting, I would rather capture the exception, present the user with a more user-friendly error (perhaps a messagebox warning) and allow them to continue operation in the app.
Is it possible to stop the app from bailing out?
The way I'm currently attempting to catch this is like the following:
public class Login : Activity
{
int count = 1;
Session mySession;
protected override void OnCreate(Bundle bundle)
{
AndroidEnvironment.UnhandledExceptionRaiser += HandleAndroidException;
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Login);
Button button = FindViewById<Button>(Resource.Id.Login);
string accountCode = Resource.Id.AccountCode.ToString();
string password = Resource.Id.Password.ToString();
// button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); };
button.Click += delegate
{
throw new Exception("LETS THROW A RANDOM EXCEPTION");
};
}
void HandleAndroidException(object sender, RaiseThrowableEventArgs e)
{
Log.Error("INTERNAL DEBUG", "PLEASE HANDLE MY EXCEPTION!");
e.Handled = true;
System.Console.Write("YOU'VE JUST BEEN HANDLED!");
}
}
As you can see I am throwing a general exception and attempting to catch this with an UnhandledExceptionRaiser. I used this as a reference: http://androidapi.xamarin.com/index.aspx?link=E%3AAndroid.Runtime.AndroidEnvironment.UnhandledExceptionRaiser
I am able to find my message in the "Android Device Logging" tool, however it is being triggered AFTER an unhandled exception error occurs. I think this means something inside of Xamarin is having first crack at the exception and falling over. Surely there has to be a way of stopping this??
I have seen countless examples online where people have been asking similar questions and there has been no clear solution. Some people have offered some solutions, but these don't actually do what I had anticipated.
It is literally mind boggling to me if this cannot be done.
This is my first time using Xamarin and also my first time developing a mobile app so I apologise if I'm being ignorant about anything.
Please help!!!
There is one important thing you have to understand about the nature of an Unhandled exception in Android, there isn't one.... in Android framework which uses Java it's an Uncaught exception which means you can't "handle" it or recover from it like you maybe would in a .Net environment. Xamarin(Mono) internally "handles" those uncaught exceptions by surrounding literally everything with try-catch and raising the Unhandled event but that is besides the point. It is also discouraged to interact with the UI as well for various reasons.
Theoretically there are several "workarounds" for displaying a dialog to the user or restarting the app, none of which I'd recommend on doing. Instead you should surround sensitive areas with try-catch clauses to handle expected exceptions, as for the unexpected one's just use an exception reporting component and update your app after analyzing the reported exceptions.
Also, I would move the event subscription to the Application class but that is a personal preference.
Like so:
public class YourAppClass : Application
{
public override void OnCreate()
{
AndroidEnvironment.UnhandledExceptionRaiser += HandleAndroidException;
}
}
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.
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);
}
}
We have a WPF application where parts of it may throw exceptions at runtime. I'd like to globally catch any unhandled exceptions and log them, but otherwise continue program execution as if nothing happened (kinda like VB's On Error Resume Next).
Is this possible in C#? And if so, where exactly would I need to put the exception handling code?
Currently I can't see any single point where I could wrap a try/catch around and which would catch all exceptions that could occur. Even then, I would have left whatever has been executed because of the catch. Or am I thinking in horribly wrong directions here?
ETA: Because many people below pointed it out: The application is not for controlling nuclear power plants. If it crashes, it's not that big a deal, but it throws random exceptions that are mostly UI-related that are a nuisance in the context where it would be used. There were (and probably still are) a few of those and since it uses a plugin architecture and may be extended by others (also students in that case; so no experienced developers that are able to write completely error-free code).
As for the exceptions that get caught: I do log them to a log file, including the complete stack trace. That was the whole point of that exercise. Just to counter those people that were taking my analogy to VB's OERN too literally.
I know that blindly ignoring certain classes of errors is dangerous and might corrupt my application instance. As said before, this program isn't mission-critical for anyone. No-one in their right mind would bet the survival of the human civilization on it. It's simply a little tool for testing certain design approaches wrt. software engineering.
For the immediate use of the application there are not many things that can happen on an exception:
No exception handling – error dialog and application exit. Experiment has to be repeated, though likely with another subject. No errors have been logged, which is unfortunate.
Generic exception handling – benign error trapped, no harm done. This should be the common case judged from all errors we were seeing during development. Ignoring this kind of errors should have no immediate consequences; the core data structures are tested well enough that they will easily survive this.
Generic exception handling – serious error trapped, possibly crash at a later point. This may happen rarely. We've never seen it so far. The error is logged anyway and a crash might be inevitable. So this is conceptually similar to the very first case, except that we have a stack trace. And in the majority of cases the user won't even notice.
As for the experiment data generated by the program: A serious error would at worst just cause no data to be recorded. Subtle changes that change the result of the experiment ever so slightly are pretty unlikely. And even in that case, if the results seem dubious the error was logged; one can still throw away that data point if it's a total outlier.
To summarize: Yes, I consider myself still at least partially sane and I don't consider a global exception handling routine which leaves the program running to be necessarily totally evil. As said twice before, such a decision might be valid, depending on the application. In this case it was judged a valid decision and not total and utter bullshit. For any other application that decision might look different. But please don't accuse me or the other people who worked on that project to potentially blow up the world just because we're ignoring errors.
Side note: There is exactly one user for that application. It's not something like Windows or Office that gets used by millions where the cost of having exceptions bubble to the user at all would be very different in the first place already.
Use the Application.DispatcherUnhandledException Event. See this question for a summary (see Drew Noakes' answer).
Be aware that there'll be still exceptions which preclude a successful resuming of your application, like after a stack overflow, exhausted memory, or lost network connectivity while you're trying to save to the database.
Example code using NLog that will catch exceptions thrown from all threads in the AppDomain, from the UI dispatcher thread and from the async functions:
App.xaml.cs :
public partial class App : Application
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
SetupExceptionHandling();
}
private void SetupExceptionHandling()
{
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
LogUnhandledException((Exception)e.ExceptionObject, "AppDomain.CurrentDomain.UnhandledException");
DispatcherUnhandledException += (s, e) =>
{
LogUnhandledException(e.Exception, "Application.Current.DispatcherUnhandledException");
e.Handled = true;
};
TaskScheduler.UnobservedTaskException += (s, e) =>
{
LogUnhandledException(e.Exception, "TaskScheduler.UnobservedTaskException");
e.SetObserved();
};
}
private void LogUnhandledException(Exception exception, string source)
{
string message = $"Unhandled exception ({source})";
try
{
System.Reflection.AssemblyName assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName();
message = string.Format("Unhandled exception in {0} v{1}", assemblyName.Name, assemblyName.Version);
}
catch (Exception ex)
{
_logger.Error(ex, "Exception in LogUnhandledException");
}
finally
{
_logger.Error(exception, message);
}
}
AppDomain.UnhandledException Event
This event provides notification of uncaught exceptions. It allows the
application to log information about the exception before the system
default handler reports the exception to the user and terminates the
application.
public App()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception) args.ExceptionObject;
Console.WriteLine("MyHandler caught : " + e.Message);
Console.WriteLine("Runtime terminating: {0}", args.IsTerminating);
}
If the UnhandledException event is handled in the default application
domain, it is raised there for any unhandled exception in any thread,
no matter what application domain the thread started in. If the thread
started in an application domain that has an event handler for
UnhandledException, the event is raised in that application domain. If
that application domain is not the default application domain, and
there is also an event handler in the default application domain, the
event is raised in both application domains.
For example, suppose a thread starts in application domain "AD1",
calls a method in application domain "AD2", and from there calls a
method in application domain "AD3", where it throws an exception. The
first application domain in which the UnhandledException event can be
raised is "AD1". If that application domain is not the default
application domain, the event can also be raised in the default
application domain.
In addition what others mentioned here, note that combining the Application.DispatcherUnhandledException (and its similars) with
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1" />
</runtime>
</configuration>
in the app.config will prevent your secondary threads exception from shutting down the application.
Here is complete example using NLog
using NLog;
using System;
using System.Windows;
namespace MyApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private static Logger logger = LogManager.GetCurrentClassLogger();
public App()
{
var currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = (Exception)e.ExceptionObject;
logger.Error("UnhandledException caught : " + ex.Message);
logger.Error("UnhandledException StackTrace : " + ex.StackTrace);
logger.Fatal("Runtime terminating: {0}", e.IsTerminating);
}
}
}
in Wpf application Project follow this Steps:
in App.xaml.cs file:
using 'System.Windows.Threading'
create App_DispatcherUnhandledException method same example.
example:
using System.Windows;
using System.Windows.Threading;
namespace Test
{
public partial class App : Application
{
void App_DispatcherUnhandledException(object sender,
DispatcherUnhandledExceptionEventArgs e)
{
// Process unhandled exception
// Prevent default unhandled exception processing
e.Handled = true;
}
}
}
in App.xaml:
add DispatcherUnhandledException="App_DispatcherUnhandledException"
for Example:
<Application x:Class="eValGr.UI.Light.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:eValGr.UI.Light"
DispatcherUnhandledException="Application_DispatcherUnhandledException">
<Application.Resources>
</Application.Resources>
</Application>
Like "VB's On Error Resume Next?" That sounds kind of scary. First recommendation is don't do it. Second recommendation is don't do it and don't think about it. You need to isolate your faults better. As to how to approach this problem, it depends on how you're code is structured. If you are using a pattern like MVC or the like then this shouldn't be too difficult and would definitely not require a global exception swallower. Secondly, look for a good logging library like log4net or use tracing. We'd need to know more details like what kinds of exceptions you're talking about and what parts of your application may result in exceptions being thrown.