I have a Universal WinRT app and I'm trying to implement global exception handling so I can prompt the user to send me a report with extra diagnostic information I've collected. (The extra diagnostic information is why I can't use the built-in handler that will log up to the Dev Portal).
I have the following code:
public App() {
InitializeComponent();
UnhandledException += OnUnhandledException;
// other stuff
}
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) {
try {
//handler
}
catch { }
throw e.Exception;
}
When I force an exception in my initial XAML page (my sign in page), e. g. hard code
throw new FileNotFoundException();
then my handler is triggered as expected. However, if I do this in my main hub page, which my start page navigates to, then it looks like my handler doesn't run. I can see the exception being thrown in the debugger, but it just gets swallowed somewhere. I can't find out where. I should mention that the app happily continues on at this point - it doesn't crash.
I've set DISABLE_XAML_GENERATED_BINDING_DEBUG_OUTPUT and DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION in my Project Properties to disable the built-in overrides, and as far as I know there's no async void situation here (e. g. Unhandled exception handler not called for Metro / WinRT UI async void event handler - although from what I've read, that kind of issue is resolved in 8.1 in any event). But there may be some kind of hidden async void thing going on that I'm not seeing.
I'm sure I'm missing something stupid. What is it?
(EDIT) It appears this is an issue when the exception is in a AppBarButton button event specifically.
(EDIT 2) A somewhat minimum repro is here: http://1drv.ms/1rSNq3i - run this in the 8.1 emulator or on an 8.1 phone, tap the button, open the commandbar, and choose sign out - this should trigger an exception and the handler, but the exception is lost. If you move the code to a button in the same page (a standard button), the handler fires.
(EDIT 3) I tried using the dispatcher in a minimal way, and it didn't change the visible result:
private void SignOutAppBarButton_Click(object sender, RoutedEventArgs e) {
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {
throw new FileNotFoundException();
}).AsTask().Wait();
}
In addition to the UnhandledException event you need to handle Frame.NavigationFailed. An exception in a page constructor results in firing NavigationFailed.
Related
Is there any way to catch the crashed form and reopen it again.
public static void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
}
Setting e.Handler to true should prevent the app from shutting down. You will then have to write some code to bring the window up again. There is no "reopen the crashed form" switch I am afraid. There is not even any notion of a "crashed form" as far as the event handler is concerned.
Please also note that keeping an application running like this will leave it in an undefined state. What you really should do is to catch the exception where it occurs and then use the Dispatcher_UnhandledException event handler as a last resort for logging any unhandled exception, perhaps displaying a user friendly message and finally shutting the application down.
I take charge of a development of an older WPF modular application using Prism Library for WPF. In this case, entry point to the application for me is an overriden Initialize() method since I have no access to the Application.MainWindow's App class. This class along with some other helper classes is compiled to EXE file and DLL's.
Currently I'm facing to a problem that I have to catch the Window.Closing event which is not raised during closing the application. Normally this piece of code which is put into the constructor (in this specific case into Initialize() method) is working as expected
Application.Current.MainWindow.Closing += (s, e) =>
{
e.Cancel = true;
};
On the other hand, event Window.Closed is fired up without any issues.
In my opinion it's not possible to associate this event handler outside of Application.MainWindow's constructor, or do I something wrong? Please help me.
The issue was located. The OnClosing method which raises the Closing event is implemented in the shell and it looks like this
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
ViewModel.StartShutdownSequence();
}
The StartShutdownSequence() encapsulates some logic regarding handling individual modules and at the end it calls Application.Current.Shutdown() which definitely shutdown the application.
I was reading C# in a nutshell (Threading chapter) and was trying to catch a divide by zero exception that I throw in a new thread from a button event handler. The AppDomain.CurrentDomain.UnhandledException fires as expected. The event handling methods simply show a window called "ErrorWindow". When I step into the constructor of the window, the debugger throw the exception back and the window doesn't show.
Here's what I have:
Target Framework: 4.5.2
Target Platform: X64
The application is a WPF windows application and contains two windows:
MainWindow: Has a button that executes the code snippet below.
ErrorWindow: Just a blank window to show in the AppDomain.CurrentDomain.UnhandledException event handler
Code snippet:
var thread = new Thread(() =>
{
int result = 100 / int.Parse("0");
});
thread.Start();
I'm attaching the AppDomain.CurrentDomain.UnhandledException event handler in a StartUp event handler in App.xaml.cs. The event handler simply create a instance of the ErrorWindow and attemtps to show it.
If someone is able to recreate this behavior and explain why, that'd be great. I'll share my VS project if needed.
PS: This only happens when I create a thread. If my DivideByZeroException gets thrown from the main UI thread, then the window shows as expected.
PS: Marshalling the showing of the window to the UI thread doesn't work and I don't expect it to.
Thanks!
IMHO the AppDomain.UnhandledException Event is not meant to show windows or error dialogs. As reported in the Remarks section:
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. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.
Instead, if you want to trap an exception and handle it, you can use the Application.DispatcherUnhandledException Event. In this case you can keep you application alive, just by setting the Handled property to true:
Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
/* Show your error window */
}
But pay attention, because:
If an exception is not handled on either a background user interface (UI) thread (a thread with its own Dispatcher) or a background worker thread (a thread without a Dispatcher), the exception is not forwarded to the main UI thread. Consequently, DispatcherUnhandledException is not raised.
I hope it cal help you.
Today I've encountered strange problem - seems that on my device (v. 8.10.14203.306) OnNavigatedFrom event is not getting called when the app is being suspended. As far as I remember some time ago it was working ok, and exacly as documentation stays:
Note On Windows Phone, OnNavigatedFrom() is called when the app is suspended. OnNavigatedTo() is not called when the app is resumed.
I've tried a simple example (available at GitHub):
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedFrom(e);
Debug.WriteLine("Navigation");
this.Background = new SolidColorBrush(Colors.Red);
}
when there is normal navigation (e.g. by back button) the event is fired, but no more when the app is suspended - both in debug and release mode. I've also checked if the Suspending event is fired and it turnes out that it is:
// uncomment this to check if app is being suspended
App.Current.Suspending += (sender, e) => this.Background = new SolidColorBrush(Colors.Blue);
Am I missing something?
The only thing I can suggest is to make sure that you're calling Frame.GetNavigationState from within your Application.Suspending handler (this is usually done by SuspensionManager.SaveAsync). According to the docs:
Calling this method will call Page.OnNavigatedFrom for the current page using NavigationMode.Forward. GetNavigationState is usually called when the application is being suspended, so the current page is navigated away from.
I am referring to http://msdn.microsoft.com/en-us/library/windows/apps/hh464925.aspx#app_activation
// App is an Application
public App()
{
this.InitializeComponent();
// Doesn't compile
//this.Activated += OnActivated;
this.Suspending += OnSuspending;
}
protected override void OnActivated(IActivatedEventArgs args)
{
System.Diagnostics.Debug.WriteLine("OnActivated");
}
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
deferral.Complete();
}
Note, OnActivated will never be triggered. OnSuspending will be triggered, after I quit the app around 30 seconds.
How can I capture Activated event? It is weird that I do not find Activated event in App, although the documentation says so.
The activation is a little confusing. Take a look at the documentation here:
http://msdn.microsoft.com/en-us/library/windows/apps/br242324.aspx
What you'll find is that when the user taps the tile, only the OnLaunched event is fired (see documentation here: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.onactivated.aspx )
The OnActivated is only for special cases outside of the ordinary launch. That would be any one of the following:
OnFileActivated
OnSearchActivated
OnShareTargetActivated
OnFileOpenPickerActivated
OnFileSavePickerActivated
OnCachedFileUpdaterActivated
So if you truly want something that is called anytime the app is activated regardless of how, I'd suggest making your own private method, then calling it from both OnLaunched and OnActivated. That should hit all cases for activation.
Maybe the problem is that you launch the app normally for example, by tapping the app tile(without facts, I'm just guessing). In this case, only the OnLaunched method is called.
msdn