Global error handling doesn't work in WPF - c#

I want to handle all unexpected errors in a WPF application. When I look at, there are different events for different situation to capture and control error. Also I added these in application constructor method
public App()
{
AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
Dispatcher.UnhandledException += OnDispatcherUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
}
However, I try that for checking handling but they didn't work. What is the reason?
private void btnStart_Click(object sender, RoutedEventArgs e) //2021112242
{
throw new StackOverflowException();
}

Every exception event has his own callback method & event object
// Dispatcher.UnhandledException
private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
}
// TaskScheduler.UnobservedTaskException
private static void OnTaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
}
// AppDomain.CurrentDomain.UnhandledException
private static void OnCurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
}
// AppDomain.CurrentDomain.FirstChanceException
private static void OnCurrentDomainUnhandledException(object sender, FirstChanceExceptionEventArgs e)
{
}

App has an event for this called DispatcherUnhandledException. This works in most cases but when the exception is thrown from a separate thread it gets a little hairy.
public partial class App
{
public App()
{
// Globally handle errors/exceptions for a friendly close.
DispatcherUnhandledException += DispatcherOnUnhandledException;
}
private void DispatcherOnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
try
{
e.Handled = true;
e.Exception.Display("An unhandled exception occurred, the application will now close.");
e.Exception.Log(); // log the problem.
Shutdown(-1); // assume not recoverable.
}
catch
{
Shutdown(-1);
}
}
}

Related

Why App.DispatcherUnhandledException handler doesn't catch exceptions thrown by App constructor?

Please look at the following code:
public partial class App : Application
{
public App():base()
{
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
throw new InvalidOperationException("exception");
}
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message);
e.Handled = true;
}
}
Why the handler doesn't catch the exception thrown by App constructor?
Why the handler doesn't catch the exception thrown by App constructor?
Simply because there is no dispatcher running before the App has been constructed.
This is the Main method that is generated for you by the compiler:
[STAThread]
static void Main(string[] args)
{
App application = new App(); //<-- your throw here
application.InitializeComponent();
application.Run(); //<-- and there is no dispatcher until here
}
From the docs:
When Run is called, Application attaches a new Dispatcher instance to the UI thread. Next, the Dispatcher object's Run method is called, which starts a message pump to process windows messages.
You cannot call Run before the you have actually created the App object.
I've worked this way to do the same.
public partial class App : Application
{
public App():base()
{
Application.Current.DispatcherUnhandledException += new
System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(
AppDispatcherUnhandledException);
throw new InvalidOperationException("exception");
}
void AppDispatcherUnhandledException(object sender,
System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//do whatever you need to do with the exception
//e.Exception
MessageBox.Show(e.Exception.Message);
e.Handled = true;
}
}
Instance of App failed to construct, therefore Application.Current doesn't make any sense. You should subscribe on AppDomain.CurrentDomain.UnhandledException
public App() : base()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
throw new InvalidOperationException("exception");
}
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(e.ExceptionObject.ToString());
}

C# Outlook Addin setCurrentFormPage throw exception

I am developing a plugin for outlook with VSTO and i am trying to put a separate form region to show as the current form page in the open inspector but throw an exception. here is the code
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.Inspectors.NewInspector += InspectorsOnNewInspector;
this.Application.Explorers.NewExplorer += Explorers_NewExplorer;
}
private void Explorers_NewExplorer(Outlook.Explorer explorer)
{
}
private void InspectorsOnNewInspector(Outlook.Inspector inspector)
{
MessageBox.Show("ola");
// exception ocurrs in this line
inspector.SetCurrentFormPage("OutlookAddIn.RequestFormRegion");
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
Thanks in advance.
I managed to put it to work with the following code
private void InspectorsOnNewInspector(Outlook.Inspector inspector)
{
MessageBox.Show("ola");
if (!(inspector.CurrentItem is Outlook.TaskItem)) return;
var taskItem = (Outlook.TaskItem) inspector.CurrentItem;
taskItem.Open += (ref bool cancel) =>
{
try
{
inspector.SetCurrentFormPage("OutlookAddIn.RequestFormRegion");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
};
}

How to look up which exception was thrown when running a WPF application?

When I start a WPF application and an exception is thrown by some method the program crashes. For debugging reasons it would be very interesting to see the exception stack. But where will it be printed?
You should hook up to the AppDomain.CurrentDomain.UnhandledException event and the Application.DispatcherUnhandledApplication event inside the App constructor or in the App.OnStartup .
public partial class App : Application
{
//Either here
public App()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
//Or here
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Dispatcher.UnhandledException += Dispatcher_UnhandledException;
}
void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//add logging
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//add logging
}
}
}
In app.xaml.cs just add an uncaught exception handler
Be aware that exceptions from unmanaged code and elude this handler
this.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
if (!string.IsNullOrEmpty(e.Exception.StackTrace))
{
sb.AppendLine("e.Exception.StackTrace ");
int count = 0;
foreach (string line in e.Exception.StackTrace.Split('\n'))
{
sb.AppendLine(line.Trim());
count++;
if (count > 10) break;
}
}

How to execute function when software ended with normal close (X) or un expected error thrown

I would like to execute a function when the running application terminated via normal close way (right top X) or un expected error happened and software terminated.
How can i do this at c# 4.5 WPF application
Thank you
In your App.xaml.cs -
Override OnStartUp method and hook UnhandledException event of
Current AppDomain, it will get called whenever application was
about to close because of some unhandled exception.
Override OnExit method for normal close of application.
Create CleanUp method and call the method from above two methods.
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
private void CleanUp()
{
// Your CleanUp code goes here.
}
protected override void OnExit(ExitEventArgs e)
{
CleanUp();
base.OnExit(e);
}
void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
CleanUp();
}
You could handle the Exit event of the app's Application subclass main instance
and the UnhandledException event of the current AppDomain instance like so:
public partial class App : Application {
public App() {
this.Exit += App_Exit;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
MessageBox.Show("Exception " + e.ExceptionObject.GetType().Name);
}
void App_Exit(object sender, ExitEventArgs e) {
MessageBox.Show("Bye bye");
}
}
Please note that given the following (simulated by clicking some buttons)
scenarios for unhandled exceptions:
which handle their respective click events like so:
private void buttonThrowNice_Click(object sender, RoutedEventArgs e) {
throw new Exception("test");
}
private void buttonStackOverflow_Click(object sender, RoutedEventArgs e) {
this.buttonStackOverflow_Click(sender, e);
}
private void buttonFailFast_Click(object sender, RoutedEventArgs e) {
Environment.FailFast("my fail fast");
}
private void buttonOutOfMemory_Click(object sender, RoutedEventArgs e) {
decimal[,,,,,] gargantuan = new decimal[int.MaxValue,int.MaxValue,int.MaxValue,int.MaxValue, int.MaxValue, int.MaxValue];
Debug.WriteLine("Making sure the compiler doesn't optimize anything: " + gargantuan.ToString());
}
The UnhandledException event of the AppDomain class only handles:
regular exceptions
the OutOfMemoryException
whereas the:
failfast
and the StackOverflow exception
are not caught.

How to call event before Environment.Exit()?

I have a console application in C#. If something goes wrong, I call Environment.Exit() to close my application. I need to disconnect from the server and close some files before the application ends.
In Java, I can implement a shutdown hook and register it via Runtime.getRuntime().addShutdownHook(). How can I achieve the same in C#?
You can attach an event handler to the current application domain's ProcessExit event:
using System;
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += (s, e) => Console.WriteLine("Process exiting");
Environment.Exit(0);
}
}
Hook AppDomain events:
private static void Main(string[] args)
{
var domain = AppDomain.CurrentDomain;
domain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
domain.ProcessExit += new EventHandler(domain_ProcessExit);
domain.DomainUnload += new EventHandler(domain_DomainUnload);
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine("MyHandler caught: " + e.Message);
}
static void domain_ProcessExit(object sender, EventArgs e)
{
}
static void domain_DomainUnload(object sender, EventArgs e)
{
}
I'd recommend wrapping the call to Environment.Exit() in your own method and using that throughout. Something like this:
internal static void MyExit(int exitCode){
// disconnect from network streams
// ensure file connections are disposed
// etc.
Environment.Exit(exitCode);
}

Categories

Resources