How do I 'globally' catch exceptions thrown in object instances - c#

I am currently writing a winforms application (C#).
I am making use of the Enterprise Library Exception Handling Block, following a fairly standard approach from what I can see. IE : In the Main method of Program.cs I have wired up event handler to Application.ThreadException event etc.
This approach works well and handles the applications exceptional circumstances.
In one of my business objects I throw various exceptions in the Set accessor of one of the objects properties
set {
if (value > MaximumTrim)
throw new CustomExceptions.InvalidTrimValue("The value of the minimum trim...");
if (!availableSubMasterWidthSatisfiesAllPatterns(value))
throw new CustomExceptions.InvalidTrimValue("Another message...");
_minimumTrim = value;
}
My logic for this approach (without turning this into a 'when to throw exceptions' discussion) is simply that the business objects are responsible for checking business rule constraints and throwing an exception that can bubble up and be caught as required. It should be noted that in the UI of my application I do explictly check the values that the public property is being set to (and take action there displaying friendly dialog etc) but with throwing the exception I am also covering the situation where my business object may not be used by a UI eg : the Property is being set by another business object for example. Anyway I think you all get the idea.
My issue is that these exceptions are not being caught by the handler wired up to Application.ThreadException and I don't understand why.
From other reading I have done the Application.ThreadException event and it handler "... catches any exception that occurs on the main GUI thread". Are the exceptions being raised in my business object not in this thread? I have not created any new threads.
I can get the approach to work if I update the code as follows, explicity calling the event handler that is wired to Application.ThreadException. This is the approach outlined in Enterprise Library samples. However this approach requires me to wrap any exceptions thrown in a try catch, something I was trying to avoid by using a 'global' handler to start with.
try
{
if (value > MaximumTrim)
throw new CustomExceptions.InvalidTrimValue("The value of the minimum...");
if (!availableSubMasterWidthSatisfiesAllPatterns(value))
throw new CustomExceptions.InvalidTrimValue("Another message");
_minimumTrim = value;
}
catch (Exception ex)
{
Program.ThreadExceptionHandler.ProcessUnhandledException(ex);
}
I have also investigated using wiring a handler up to AppDomain.UnhandledException event but this does not catch the exceptions either.
I would be good if someone could explain to me why my exceptions are not being caught by my global exception handler in the first code sample. Is there another approach I am missing or am I stuck with wrapping code in try catch, shown above, as required?

As a thought, try adding (fairly early on - i.e. at the start of Main):
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
That said - it seems to work fine for me with or without...

According to MSDN, Application.ThreadException will only be fired if the exception isn't handled. Maybe there is a catch somewhere up the callstack that is handling the exception?
Another option would be to try using AppDomain.UnhandledException instead. It is the same as Application.ThreadException, except it works for all exceptions in the same AppDomain.

If you try to use use
Application.ThreadException
or
AppDomain.CurrentDomain.UnhandledException
the Debugger will catch the exception!
To test these methods you have to start the appication without a debugger.

Related

How to try/catch all exceptions

I'm completing a UWP app started by someone else. The app crashes frequently and I always end up in App.g.i.cs at
if (global::System.Diagnostics.Debugger.IsAttached)
global::System.Diagnostics.Debugger.Break();
where I then have to say "no, don't start the debugger" and close 2 windows.
Is there somewhere I could put a big try/catch so that I don't have to restart the app each time this happen? I can't find anything in AppShell or App.
Or do I have to put a try/catch in every single event handler?
If you want to avoid starting the new debugger and restarting the app each time when encountering unhandled exceptions, you can use Application.UnhandledException event and set the Handled property of the event arguments to true like following:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.UnhandledException += (sender, e) =>
{
e.Handled = true;
System.Diagnostics.Debug.WriteLine(e.Exception);
};
}
The UnhandledException event is used to notify the app about exceptions encountered by the XAML framework or by the Windows Runtime in general that have not been handled by app code.
Normally after the UnhandledException event is fired, the Windows Runtime terminates the app because the exception was unhandled. The app code has some control over this: if the UnhandledException event handler sets the Handled property of the event arguments to true, then in most cases the app will not be terminated.
For more info, please see Remarks of Application.UnhandledException event and the blog: Strategies for Handling Errors in your Windows Store Apps.
As far as i know most you cant do what you are trying to do (big try catch block) and for all intents and purposes you shouldn't even consider that possibility.
First try to determine why the app is crashing, on what page, is it when you try to something specific, the same thing everytime and then you can try catch some of the methods on that particular page and determine what's causing the crash
If you want to treat the cause rather than the symptoms, you should enable first-chance exceptions in the debugger settings. Then the debugger should break at the source of the exception, rather than in the global handler. You can then address the root cause of the problems directly.
Shipping an app that has the global handler blindly set every exception as "handled" even when you don't know why it's failing is not a good solution.
You can try/catch in your main app to catch all exceptions. Shown is an example using Xamarin Forms DisplayAlert:
try
{
//throw new Exception("gone and done it");
MyMainProgram();
}
catch (Exception ex)
{
await DisplayAlert("Whoops!", ex.Message, "ok");
throw ex;
}
You can test this by uncommenting the "throw new Exception". Execution stops with an alert you must answer, then continues by throwing the exception to prevent executing corrupted code.

Any way to catch an exception occurring on a thread I don't own?

I'm using a crappy third party library because unfortunately I have no choice. This library creates a bunch of threads internally when I call it, and occasionally throws a NullReferenceException on one of these threads. Is there any way for me to catch these exceptions even though I don't own the thread that throws them? I have no way to change the third party code.
As a simple example to show the problem:
public static void main()
{
try
{
var crappyLib = new CrappyLibrary();
crappyLib.DoCrappyThings();
}
catch
{
Console.WriteLine("This never happens");
}
}
// I do not own the following code, I can't change it
public class CrappyLibrary
{
public void DoCrappyThings()
{
var t = new Thread(DoWork);
t.Start();
}
private void DoWork()
{
throw new ThisLibrarySucksException();
}
}
The thing worrying me most in the described case is abnormal thread termination inside that 3rd-party lib. Once a thread is throwing, you can't catch the exception via correct way because you're not the owner of that thread invocation (and it has no idea it should propagate the exception to you; unlike it happens in TPL, let say). So even if handling such exceptions via a global handler this could be incorrect way because the lib can appear in non-consistent state after any of such exceptions.
So the safe way here is to isolate the lib inside some scope and re-launch the scope after any exception. Let say, to load the lib into separate domain.
If your goal is to prevent early termination of your process because of these unhandled exceptions that are not under your control, then there exists the legacyUnhandledExceptionPolicy setting that you can add to your app.config that will prevent unhandled thread exceptions from terminating the whole process.
Obviously, the solution is not perfect, as unhandled exceptions can destabilize the state of the threads. But at least it's an option you can consider.
Please have a look at the documentation about this here to better understand the implications of turning on this setting.
Your app.config would have to look something like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1"/>
</runtime>
</configuration>
EDIT:
Just a thought, but perhaps the above setting, in combination with adding an event handler for AppDomain.UnhandledException can help you with your need.
Using AppDomain.UnhandledException, you can detect the failure, so that you know when you need to trigger a retry, or whatever else it is that you need to do in these cases.
And the legacyUnhandledExceptionPolicy setting would still be useful to prevent the process from shuting down, thus giving you the opportunity to perform the retry.
I hope this is helpful https://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx
You can try something like that (it's from the article)
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);

Why exceptions do not bubble beyond WPF dialog closing event handler?

In MainFile:
Window window = new MyDialogWindow();
try
{
window.ShowDialog();
}
catch
{
// This is never called !
}
In MyDialogWindow:
private void MyDialogWindow_Closing( object sender, CancelEventArgs e )
{
throw new Exception();
}
It seems that the exception thrown into the closing event handler never reach the catch block of the caller. Do you know why ?
EDIT: I should mention I've checked that MyDialogWindow_Closing is called after I press on the close button.
EDIT2: When listening to AppDomain.CurrentDomain.UnhandledException, the event is fired !
I would guess that you are getting an exception that is not your thrown exception, but instead another exception that is not normally 'caught' by the .Net exception handling umbrella. One such class of exceptions are structured error handling exceptions (SEH) which typically occur when there are issues (usually memory issues, or pointer issues) in unmanaged code that crash in that execution, but can't be bubbled up into the .Net exception handling stream.
Go into your Debug-->Exceptions, and check everything. Then run your program. You will almost certainly find out what your exception truly is.
It can't hurt to look at this question as well which discusses the topic.

Throw single custom exception from Class Library

How can I write a catch all exception handler in a Class Library project in C#, which will give the outside caller only one Custom Exception on any exception occurring in the library.
Most nearest solution I found is to implement a Facade class, call low level classes from it, and write try..catch in every call from Facade which will throw single custom exception if any exception occurs underneath.
I searched for solutions, but got it only for Web Applications (using Application context for catching exceptions)
e.g. How to implement one "catch'em all" exception handler with resume?
I need to implement it at Class Library level or at consumer of library level, but good if that can be done by write minimum exception handling statements.
You could use:
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
var exception = e.ExceptionObject as Exception;
if (exception != null && exception.Source == "MyLib")
{
// Do stuff here
}
};
But seriously, don't do it. Exceptions shouldn't be handled this way, you should catch them locally.
You could use AppDomain.UnhandledException but make sure you read the documentation thoroughly - there are some exceptions that you can't handle, and it also depends on version of the framework that you are using.

Why isn't my exception being caught

I have an application that is mixed Winforms and WPF. In Winforms, I have a global exception handler that is defined as follows:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
This ALWAYS catches exceptions anywhere in my application that occur that are not expected and handled gracefully.
For WPF, all I seem to be able to capture is:
wpfAppDomain = new System.Windows.Application();
wpfAppDomain.DispatcherUnhandledException +=
wpfAppDomain_DispatcherUnhandledException;
This does NOT always catch global exceptions, and I often find that exceptions are swallowed somewhere and I'm not sure why.
How can I make a global exception handler for WPF that can catch any exception that occurs that is unhandled?
There are several cases where this code will not catch an exception and do so by design
The exception is simply uncatchable. For example a runtime thrown StackOverflowException
The exception is unhandled in your code, but caught in the core WPF framework.
There is no way to catch all thrown exceptions. To do so would allow you to violate semantics of code that should always work.
Have you tried this after calling SetUnhandledExceptionMode? Like this:
// Force all exceptions through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
DispatcherUnhandledException only catches exception from code called by a dispatcher (like the name suggests), it is supposed to catch exceptions thrown when called from WPF code.
It does not cover exceptions thrown from: WinForms, BackgroundWorker, the thread pool or threads you started yourself.
you can still use AppDomain.CurrentDomain.UnhandledException to catch those.

Categories