How to catch exceptions for objects defined in XAML in WPF - c#

Is there a way to catch Exceptions from Objects declared in XAML such as a StoryBoard and keep the application from crashing completely?
In this particular case users will rarely encounter an exception relating to an un-animatable or unaccessible property path. I am working to address these issues but in general the app is critical and I would like to prevent it from simply crashing in these instances.
The app is a UserControl that is Hosted in a windows forms app via ElementHost.
How do you handle these types of exceptions and keep the app running?
Some additional info
I tried using something like:
Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
as a means of catching the exceptions but Application.Current is always null so I can't use it.
In a nutshell I need to ensure that no matter what happens the app itself continues to run.

Oh the horror when you get xaml related crash errors! :) I don't have the full receipt in my head here right now, and I need more information about your issue, but make sure to hook on to all following error handlers(App.xaml.cs in WPF, check link below for forms).
DispatcherUnhandledException += UnhandledDispatcherException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
private void UnhandledDispatcherException(Object sender, DispatcherUnhandledExceptionEventArgs e)
{
// do your stuff here!
e.Handled = true; // Ex is now handled and will not crash your app
}
This one is forms only I think(dont have my devbox here).
Application.ThreadException += UnhandledThreadException
Add your handlers and log/System.Diagnostics.Trace.WriteLine/breakpoint away!
Check this example from MSDN regarding AppDomain. Verify that AppDomain.Current is not null when starting as well.
Snippet:
public class Example
{
[SecurityPermission(SecurityAction.Demand,Flags=SecurityPermissionFlag.ControlAppDomain)]
public static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
...
}
}
You may also do this after your InitializeComponents, if Application.Current is null.
if (System.Windows.Application.Current == null)
new System.Windows.Application();
And ofc check your debug output! :)
Hope it helps,
Cheers
Stian

Related

Stack overflow after an exception in Control.LayoutUpdated if DispatcherUnhandledException is registered

Recently, I was running into a problem which I'm still breaking my head over. In an application, I registered a dispatcher exception handler. In the same application, a third-party-component (DevExpress Grid Control) causes an exception within the event handler for Control.LayoutUpdated. I expect, that the dispatcher exception handler is triggered once. But instead, I get a stack overflow. I produced a sample without the third party component and discovered, that it happens in every WPF application.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace MyApplication
{
/* App.xaml
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyApplication.App"
Startup="OnStartup"
/>
*/
public partial class App
{
private void OnStartup(object sender, StartupEventArgs e)
{
DispatcherUnhandledException += OnDispatcherUnhandledException;
MainWindow = new MainWindow();
MainWindow.Show();
}
private static void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message);
e.Handled = true;
}
}
public class MainWindow : Window
{
private readonly Control mControl;
public MainWindow()
{
var grid = new Grid();
var button = new Button();
button.Content = "Crash!";
button.HorizontalAlignment = HorizontalAlignment.Center;
button.VerticalAlignment = VerticalAlignment.Center;
button.Click += OnButtonClick;
mControl = new Control();
grid.Children.Add(mControl);
grid.Children.Add(button);
Content = grid;
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
mControl.LayoutUpdated += ThrowException;
mControl.UpdateLayout();
mControl.LayoutUpdated -= ThrowException;
}
private void ThrowException(object sender, EventArgs e)
{
throw new NotSupportedException();
}
}
}
Is there any way to prevent this behavior? It happens with .NET framework 3.0, 3.5, 4.0 and 4.5. I can't just wrap a try-catch around the LayoutUpdated event handler since it is in a third party component and I don't think, a stack overflow should happen.
I think Florian GI is right about the message box, but if instead of a message box you did something else (or nothing i.e. just set Handled to true) in the OnDispatcherUnhandledException method it still loops forever and doesn't get to the mControl.LayoutUpdated -= ThrowException; line.
So I thought I would have a little snop through the code with dotPeek...
When you call UpdateLayout on the control, ultimately it gets to the method ContextLayoutManager.UpdateLayout and a snippet of this method looks like this:
// ... some code I snipped
bool flag2 = true;
UIElement element = (UIElement) null;
try
{
this.invalidateTreeIfRecovering();
while (this.hasDirtiness || this._firePostLayoutEvents)
{
//... Loads of code that I think will make sure
// hasDirtiness is false (since there is no reason
// for anything remaining dirty - also the event is
// raised so I think this is a safe assumption
if (!this.hasDirtiness)
{
this.fireLayoutUpdateEvent();
if (!this.hasDirtiness)
{
this.fireAutomationEvents();
if (!this.hasDirtiness)
this.fireSizeChangedEvents();
}
}
//... a bit more
flag2 = false;
}
}
finally
{
this._isUpdating = false;
this._layoutRequestPosted = false;
//... some more code
if (flag2)
{
//... some code that I can't be bothered to grok
this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Delegate) ContextLayoutManager._updateLayoutBackground, (object) this);
}
}
// ... and for good measure a smidge more code
I'm going to take a punt and suggest that the _firePostLayoutEvents flag is true in your case.
The only place where _firePostLayoutEvents is set to false is in the fireAutomationEvents method so let's assume that somewhere before the end of the fireAutomationEvents method your exception is thrown (I would guess the fireLayoutUpdateEvent method) so this flag will not get set to false.
But, of course, the finally is outside the loop so it will not loop forever (and if it did you'd not get a StackOverflowException).
Right, onward, so we are invoking the UpdateLayoutBackground function, which actually just calls NeedsRecalc so let's look at that...
private void NeedsRecalc()
{
if (this._layoutRequestPosted || this._isUpdating)
return;
MediaContext.From(this.Dispatcher).BeginInvokeOnRender(ContextLayoutManager._updateCallback, (object) this);
this._layoutRequestPosted = true;
}
Rightyho, that is calling the UpdateLayoutCallback so squinting at that...
private static object UpdateLayoutCallback(object arg)
{
ContextLayoutManager contextLayoutManager = arg as ContextLayoutManager;
if (contextLayoutManager != null)
contextLayoutManager.UpdateLayout();
return (object) null;
}
Oooooh, that is interesting - it's calling UpdateLayout again - I would, therefore, hazzard a slightly educated guess that that is the root cause of your problem.
Therefore, I don't think there is anything much you can do about it I am afraid.
I am not quite sure about the following, but maybe it's a guess in the right direction.
In MSDN it sais:
However, LayoutUpdated can also occur at run time during the object
lifetime, for a variety of reasons: a property change, a window
resizing, or an explicit request (UpdateLayout or ApplyTemplate).
So it might get also fired after a MessageBox has shown?
If thats the case a MessageBox would open through an unhandled exception, which fires the LayoutUpdated-EventHandler and this again raises an unhandled exception. This would lead to an endless loop and after a while to the stack overflow.
If you do not throw an unhandled exception in the LayoutUpdated-EventHandler, but call the MessageBox.Show()-method it also ends in an endless loop, what would proof my point.
I realize I'm over four years late to the party, but maybe someone will find this useful...
Your application's dispatcher does not stop responding to input and layout events during the call to MessageBox.Show(). The LayoutUpdated event fires any time there is any layout-related work to do, which happens far more often than you might expect. It will continue to fire while the message box is displayed, and if whatever condition triggered the error continues to persist, new exceptions will be raised, and your handler will show more and more message boxes. And because MessageBox.Show() is a blocking call, it's not going to disappear from the call stack until it returns. Subsequent invocations of your handler will be pushed deeper and deeper into the dispatcher's call stack until it overflows.
You really have two separate problems:
Your code to display a crash dialog is reentrant.
Your application continues to raise exceptions on the dispatcher thread while your crash dialog is being displayed.
You could solve the first issue with a non-reentrant queue. Rather than displaying the crash dialog immediately, have your handler place the exception in a queue. Have your handler process the queue only if you are not already processing it farther up the stack. This prevents multiple crash dialogs from being shown simultaneously, and should keep your call stack from growing too deep, thus avoiding your stack overflow issue.
To address the second problem, you should probably shut down the offending part of your application as soon as you see the first exception (and before you show the crash dialog). Alternatively, you could devise a way to filter out duplicate exceptions and ensure that equivalent errors don't end up in the queue at the same time. But given how rapidly the exceptions are recurring, I would choose the first option.
Keep in mind that you need to address both of these issues. If you don't address the second issue, you'll likely end up trading in your StackOverflowException for an OutOfMemoryException. Or you'll show an infinite number of crash dialogs, one after the other. Either way, it'll be bad.

How can I get WinForms to stop silently ignoring unhandled exceptions?

This is getting extremely irritating. Right now I have a winforms application, and things were not working right, but no exceptions were being thrown as far as I could tell. After stepping through almost all pieces of relevant code, it turns out that an exception was being thrown at the start of my application.
Long story short, in WinForms, being as awesome as it is, if an exception occurs the WinForms library ignores it. No "an unhandled exception has occurred" JIT message is thrown, it just stops processing the current event and goes back to the GUI.
This is causing random bugs, because code to load data isn't being called due to the exception occurring prior to this data being loaded.
To see this in action I created a brand new WinForms application, and entered the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string blah = null;
blah.Trim();
}
}
Press F5 and the form loads without any errors showing, even though a null reference is being thrown.
I then tried to go to my Program.cs main method and add Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); to it. Still my form loads without causing any errors to be thrown.
Even though I know that I can tell VS to break on all exceptions, I find this situation really bad. It causes really wierd issues that are hard to debug in production, and as this is an internal tool I really want to have it so it actually errors out when an exception occurs, and not silently disregards it.
Does anyone know how to do this?
Update: Just to update on things I have learned from the comments.
This does appear to be a 64-bit issue with windows, as I learned from this question which I did not see before posting. In that question it pointed to a Microsoft bug report about this, which had this to say:
Hello,
This bug was closed as "External" because this behavior results from how x64 version of Windows handle exceptions. When a user mode exception crosses a kernel transition, x64 versions of Windows do not allow the exception to propagate. Therefore attached debuggers are unaware of the fact that an exception occured resulting in the debugger failing to break on the unhandled exception.
Unfortunately where is nothing that the Visual Studo team can do to address this, it is the result of operating system design. All feedback regarding this issue should be addressed to the Windows team; however the Windows team considers this to be the "correct" operating system design, and considers the x86 behavior to be "incorrect".
Best Regards,
Visual Studio Debugger
That being said, builds not run through visual studio (or using Ctrl+F5 to run) does seem to show the JIT exception message box EXCEPT if you have the following code in your Program.cs:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
That code will cause windows to ignore the exception.
However, if you (instead) subscribe to the Application.ThreadException event, not only will your exceptions be caught, visual studio's debugger will break on unhandled exceptions!
In your Program.cs' Main function you should also ensure that you've wrapped your call to open the form in a try/catch. Additionally use the AppDomain.UnhandledException to catch exceptions. We also add Application.ThreadException too.
I believe the following will give you hooks into all the exceptions that can be thrown...
static void Main()
{
try
{
System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
var form = new MainForm();
form.ShowDialog();
}
catch (Exception e)
{
HandleUnhandledException(e);
}
finally
{
// Do stuff
}
}
private static void HandleUnhandledException(Object o)
{
// TODO: Log it!
Exception e = o as Exception;
if (e != null)
{
}
}
private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
HandleUnhandledException(e.ExceptionObject);
}
private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
HandleUnhandledException(e.Exception);
}
Try the following.
Handle exceptions in your main application entry point.
Also, manage unhandled thread exceptions using a ThreadExceptionEventHandler
This is the code snippet:
[STAThread]
public static void Main(string[] args)
{
try
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
//your program entry point
}
catch (Exception ex)
{
//manage also these exceptions
}
}
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
ProcessException(e.Exception);
}
An easy fix is not to run under the debugger.
The debugger is masking the exception for some reason. If you run your app normally (Ctrl+F5), you'll get the usual "Unhandled exception has occurred in your application... Continue/Quit?" dialog.
Having experienced this often and identified the issue regarding 64 bit OS and the Form.Load event, I always just make a point of doing all my start up functions in the Form.Shown event. For all practical purposes this is the same thing (aside from a few rare, exceptional circumstances), and the JIT message is produced in the Shown event.

How can I set up .NET UnhandledException handling in a Windows service?

protected override void OnStart(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Thread.Sleep(10000);
throw new Exception();
}
void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
}
I attached a debugger to the above code in my windows service, setting a breakpoint in CurrentDomain_UnhandledException, but it was never hit. The exception pops up saying that it is unhandled, and then the service stops. I even tried putting some code in the event handler, in case it was getting optimized away.
Is this not the proper way to set up unhandled exception handling in a windows service?
The reason that the UnhandledException event on the current AppDomain does not fire is how services are executed.
User sends a Start command from the Windows Service Control Manager (SCM).
The command is received by the framework's ServiceBase implementation and dispatched to the OnStart method.
The OnStart method is called.
Any exception which is thrown by OnStart is handled in the base class, logged to the Event Log, and translated into an error status code returned to the SCM. So the exception never propagates to the AppDomain's unhandled exception handler.
I think you would find that an unhandled exception thrown from a worker thread in your service would be caught by the AppDomain's unhandled exception handler.
In a Windows Service you do NOT want to be running much code in the OnStart method. All you want there is the code to launch your service thread and then return.
If you do that you can handle exceptions that happen in your service thread just fine.
e.g.
public static void Start()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
running = true;
ThreadStart ts = new ThreadStart(ServiceThreadBody);
thread = new Thread(ts);
thread.Name = "ServiceThread";
thread.Priority = ThreadPriority.BelowNormal;
thread.Start();
}
When I was working on my own Windows Service, it was stoping itself oddly enough. I thought it was because of unhanded exception. At the moment I am catching unhanded exceptions on text file. First of all you have to create new file ServiceLog.txt on C locations due to logging excaptions on text file. With below coding I got all unhanded exceptions with them line numbers.
using System.Security.Permissions;
using System.IO;
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
protected override void OnStart(string[] args)
{ AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
...
Your codes...
....
}
void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace);
}
private void WriteToFile(string text)
{
string path = "C:\\ServiceLog.txt";
using (StreamWriter writer = new StreamWriter(path, true))
{
writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
writer.Close();
}
}
Know this thread is a bit old, but thought it would be useful to add some comments based on personal experience developing Windows services in .NET. The best approach is to avoid developing under the Service Control Manager as much as you can - for this you need a simple harness that mimics the way services get started - something that can create an instance of your service class (that you already derived from ServiceBase) and call your OnStart, OnStop etc methods. This harness can be a console app or a Windows app as you desire.
This is pretty much the only way I have found of debugging service start-up issues in .NET - the interaction between your code, Visual Studio and the real Service Control Manager just makes the process impossible otherwise.
HTH.
Just curious, what are you trying to accomplish: avoiding service crashing, or reporting errors?
For reporting, I think your best bet is to add top-level try/catch statements. You can try to log them to the Windows event log and/or a log file.
You can also set the ExitCode property to a non-zero value until you successfully stop the service. If the system administrator starts your service from the Services control panel, and your service stops suddenly with a non-zero exit code, Windows can show an error message with the description of the error.

Exception Handling in SCSF

I have a SCSF application i am trying to handle most of the exceptions using
Application.ThreadException += new ThreadExceptionEventHandler(new ThreadExceptionHandler().ApplicationThreadException);
The event handler :-
public class ThreadExceptionHandler
{
public void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "An exception occurred:", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Works fine . I can catch all the application exceptions in this block.
But the problem is after handling the exception the code again goes and executes the same exception generating code again. This happens till the time I get a windows message windows to send the error info to microsoft.
Could any one please help in telling me where I might be going wrong.
Thanks in Advance
Vikram
Note :- Currently i am throwing
New Exception("Test Exception"); from a button event. I am doing this to provide event handling in my application.
You have to set
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
See this MSDN page for example code
But note that this kind of catch-all exception handling is not a good replacement for exception handling inside your logic. It is a good backup, but the best thing to do in a global handler is to log the information and exit. Your app could be in an unsafe/undefined state.
After some banging my head against the code I found that the problem was due to the fact that my SCSF solution had a winforms Shell and on that shell there were WPF usercontrols.
When the exception where generated on these WPF usercontrol (mostly the case) they are not caught by
Application.ThreadException coz Application class for WPF is different than that for Winforms.
In WPF application one need to handle Application.DispacherUnhandledException event.
Just my little finding ...
you would be surprised by just handling the Application.DispatcherUnhandledException. I have worked with SCSF which had WPF user controls. Read through this post . http://social.msdn.microsoft.com/forums/en-US/wpf/thread/c57cac13-f960-49a1-94b5-a3fd316ac4bc/ i would recommend handling AppDomain.UnhandledException too.

Any way to remove notify icon in event of a crash?

Is there any way to automatically remove a NotifyIcon in the event of a crash? (I know you can mouse-over to remove it)
I'm running windows xp.
For C#, try handling the UnhandledException event from the AppDomain, so, in your Main() method add:
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
And then add the following method:
static void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
// .... Remove Notification icon here
}
Unfortunately the answer is no - Rob's answer actually detects the crash and attempts to remove the icon in the crash handler which has its own set of issues (for instance it assumes that enough of the CLR is running at the time of the crash to execute the unhandled exception, that's not always the case).
The problem here is that the shell (which runs the Shell_NotifyIcon code) gets out of sync with your application.

Categories

Resources