we're having an application on server instance and quite rarely, but we have out of memory exception (program is not leaking, just instance is quite small and it operates with quite big amounts of data).
That would be not a problem, as we monitor processes on that server instance and if some of the processes are not found in process list, alert email is sent.
Now the problem is with this:
That prevents process from disappearing from process list, so we don't get alert email about it's failure. Is it possible to disable this message, that if program fails on something we don't catch, it would close without user interaction?
Assuming Windows Forms, I typically do multiple steps to prevent this message box.
First, I connect several handlers in the Main function:
[STAThread]
private static void Main()
{
Application.ThreadException +=
application_ThreadException;
Application.SetUnhandledExceptionMode(
UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException +=
currentDomain_UnhandledException;
Application.Run(new MainForm());
}
Those handlers are being called when an otherwise unhandled exception occurs. I would define them something like:
private static void application_ThreadException(
object sender,
ThreadExceptionEventArgs e)
{
doHandleException(e.Exception);
}
private static void currentDomain_UnhandledException(
object sender,
UnhandledExceptionEventArgs e)
{
doHandleException(e.ExceptionObject as Exception);
}
The actual doHandleException function that is then called does the actual error handling. Usually this is logging the error and notifying the user, giving him the options to continue the application or quit it.
An example from a real-world application looks like:
private static void doHandleException(
Exception e)
{
try
{
Log.Instance.ErrorException(#"Exception.", e);
}
catch (Exception x)
{
Trace.WriteLine(string.Format(
#"Error during exception logging: '{0}'.", x.Message));
}
var form = Form.ActiveForm;
if (form == null)
{
MessageBox.Show(buildMessage(e),
"MyApp", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show(form, buildMessage(e),
"MyApp", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
With the helper function:
public static string buildMessage(Exception exception)
{
var result = new StringBuilder();
while (exception != null)
{
result.AppendLine(exception.Message);
result.AppendLine();
exception = exception.InnerException;
}
return result.ToString().Trim();
}
If you are using not Windows Forms but e.g. a Console application or WPF, some handlers are not present, while others are present instead.
The idea stays the same: Subscribe to event handlers that are being called if you have no try...catch around your code blocks.
Personally, I try to have as few of those try...catch blocks as possible (ideally none).
don't know if you can deactivate this - but I think you should not.
Find the bug/problem in your application and handle the problem with a craceful shutdown or by preventing the problem in first case.
Everything else will be a real crude workaround and I don't think your client will be pleased to have such a behavior (after all won't there be data lost? If not this has allways the buggy / not finished touch)
You could put a global try/catch block in your program and exit the program on any unexpected exception.
If using WPF you can try-catch the following two exceptions in your app.xaml.cs. There may be other/complementary exceptions to handle, but this are the two I am usually looking for:
AppDomain.CurrentDomain.UnhandledException - "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."
Dispatcher.UnhandledException - "Occurs when a thread exception is thrown and uncaught during execution of a delegate by way of Invoke or BeginInvoke."
ie:
public partial class App : Application
{
public App()
{
this.Dispatcher.UnhandledException += DispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
}
private void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// log and close gracefully
}
private new void DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
// log and close gracefully
}
}
Related
I am trying to understand how a C# program handles an unhandled Exception.
I am doing my testing in a windows forms project, If the answer is different in other project types, please let me know.
I am running the program from the .exe file and not from the visual studio debugger.
Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//timer1.Interval = 10000
private void timer1_Tick(object sender, EventArgs e)
{
//throw new Exception(Thread.CurrentThread.ManagedThreadId.ToString() + " This is an exception");
}
}
static class Program
{
static Form1 newForm;
static void Main()
{
Thread FormThread = new Thread(NewForm);
FormThread.Start();
Thread.Sleep(5000);
//throw new Exception(Thread.CurrentThread.ManagedThreadId.ToString() + " This is an exception");
}
static void NewForm()
{
newForm = new Form1();
Application.Run(newForm);
}
}
My question is what will be the windows response for an unhandled Exception in a C# program?
in the above example:
If the exception is thrown from the timer1_Tick function (by deleting the comment prefix) I am getting the following message:
If the exception is thrown from the Main function (by deleting the comment prefix) I am getting the following message:
why I am getting 2 different messages and how the windows/program "choose" which message to pop.
Thank you.
In a WinForms application, event handlers are invoked by the WindowsFormsSynchronizationContext. When an event handler throws an unhandled exception, the context handles it by displaying the first error dialog. At that point the synchronization context (which is simply a message pump) is still running and it could still proceed handling other events, so you are given a choice.
The Main method, in contrast, is invoked by the operating system itself, to start the application. If there is an unhandled exception there, WIndows has no option but to terminate the application, and it shows the second dialog to inform you of this.
This question already has answers here:
Globally catch exceptions in a WPF application?
(7 answers)
Closed 6 years ago.
Sometimes, under not reproducible circumstances, my WPF application crashes without any message. The application simply close instantly.
Where is the best place to implement the global Try/Catch block. At least I have to implement a messagebox with: "Sorry for the inconvenience ..."
You can trap unhandled exceptions at different levels:
AppDomain.CurrentDomain.UnhandledException From all threads in the AppDomain.
Dispatcher.UnhandledException From a single specific UI dispatcher thread.
Application.Current.DispatcherUnhandledException From the main UI dispatcher thread in your WPF application.
TaskScheduler.UnobservedTaskException from within each AppDomain that uses a task scheduler for asynchronous operations.
You should consider what level you need to trap unhandled exceptions at.
Deciding between #2 and #3 depends upon whether you're using more than one WPF thread. This is quite an exotic situation and if you're unsure whether you are or not, then it's most likely that you're not.
You can handle the AppDomain.UnhandledException event
EDIT: actually, this event is probably more adequate: Application.DispatcherUnhandledException
A quick example of code for Application.Dispatcher.UnhandledException:
public App() {
this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
}
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {
string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message);
MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
// OR whatever you want like logging etc. MessageBox it's just example
// for quick debugging etc.
e.Handled = true;
}
I added this code in App.xaml.cs
I use the following code in my WPF apps to show a "Sorry for the inconvenience" dialog box whenever an unhandled exception occurs. It shows the exception message, and asks user whether they want to close the app or ignore the exception and continue (the latter case is convenient when a non-fatal exceptions occur and user can still normally continue to use the app).
In App.xaml add the Startup event handler:
<Application .... Startup="Application_Startup">
In App.xaml.cs code add Startup event handler function that will register the global application event handler:
using System.Windows.Threading;
private void Application_Startup(object sender, StartupEventArgs e)
{
// Global exception handling
Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(AppDispatcherUnhandledException);
}
void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
\#if DEBUG // In debug mode do not custom-handle the exception, let Visual Studio handle it
e.Handled = false;
\#else
ShowUnhandledException(e);
\#endif
}
void ShowUnhandledException(DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
string errorMessage = string.Format("An application error occurred.\nPlease check whether your data is correct and repeat the action. If this error occurs again there seems to be a more serious malfunction in the application, and you better close it.\n\nError: {0}\n\nDo you want to continue?\n(if you click Yes you will continue with your work, if you click No the application will close)",
e.Exception.Message + (e.Exception.InnerException != null ? "\n" +
e.Exception.InnerException.Message : null));
if (MessageBox.Show(errorMessage, "Application Error", MessageBoxButton.YesNoCancel, MessageBoxImage.Error) == MessageBoxResult.No) {
if (MessageBox.Show("WARNING: The application will close. Any changes will not be saved!\nDo you really want to close it?", "Close the application!", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
Application.Current.Shutdown();
}
}
Best answer is probably https://stackoverflow.com/a/1472562/601990.
Here is some code that shows how to use it:
App.xaml.cs
public sealed partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
// setting up the Dependency Injection container
var resolver = ResolverFactory.Get();
// getting the ILogger or ILog interface
var logger = resolver.Resolve<ILogger>();
RegisterGlobalExceptionHandling(logger);
// Bootstrapping Dependency Injection
// injects ViewModel into MainWindow.xaml
// remember to remove the StartupUri attribute in App.xaml
var mainWindow = resolver.Resolve<Pages.MainWindow>();
mainWindow.Show();
}
private void RegisterGlobalExceptionHandling(ILogger log)
{
// this is the line you really want
AppDomain.CurrentDomain.UnhandledException +=
(sender, args) => CurrentDomainOnUnhandledException(args, log);
// optional: hooking up some more handlers
// remember that you need to hook up additional handlers when
// logging from other dispatchers, shedulers, or applications
Application.Dispatcher.UnhandledException +=
(sender, args) => DispatcherOnUnhandledException(args, log);
Application.Current.DispatcherUnhandledException +=
(sender, args) => CurrentOnDispatcherUnhandledException(args, log);
TaskScheduler.UnobservedTaskException +=
(sender, args) => TaskSchedulerOnUnobservedTaskException(args, log);
}
private static void TaskSchedulerOnUnobservedTaskException(UnobservedTaskExceptionEventArgs args, ILogger log)
{
log.Error(args.Exception, args.Exception.Message);
args.SetObserved();
}
private static void CurrentOnDispatcherUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)
{
log.Error(args.Exception, args.Exception.Message);
// args.Handled = true;
}
private static void DispatcherOnUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)
{
log.Error(args.Exception, args.Exception.Message);
// args.Handled = true;
}
private static void CurrentDomainOnUnhandledException(UnhandledExceptionEventArgs args, ILogger log)
{
var exception = args.ExceptionObject as Exception;
var terminatingMessage = args.IsTerminating ? " The application is terminating." : string.Empty;
var exceptionMessage = exception?.Message ?? "An unmanaged exception occured.";
var message = string.Concat(exceptionMessage, terminatingMessage);
log.Error(exception, message);
}
}
In addition to the posts above:
Application.Current.DispatcherUnhandledException
will not catch exceptions that are thrown from a thread other than the main thread. You have to catch those exceptions on the same thread they are thrown. But if you want to Handle them on your global exception handler you can pass it to the main thread:
System.Threading.Thread t = new System.Threading.Thread(() =>
{
try
{
...
//this exception will not be catched by
//Application.DispatcherUnhandledException
throw new Exception("huh..");
...
}
catch (Exception ex)
{
//But we can handle it in the throwing thread
//and pass it to the main thread wehre Application.
//DispatcherUnhandledException can handle it
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action<Exception>((exc) =>
{
throw new Exception("Exception from another Thread", exc);
}), ex);
}
});
To supplement Thomas's answer, the Application class also has the DispatcherUnhandledException event that you can handle.
A complete solution is here
it's explained very nice with sample code. However, be careful that it does not close the application.Add the line
Application.Current.Shutdown();
to gracefully close the app.
As mentioned above
Application.Current.DispatcherUnhandledException will not catch
exceptions that are thrown from another thread then the main thread.
That actual depend on how the thread was created
One case that is not handled by Application.Current.DispatcherUnhandledException is System.Windows.Forms.Timer for which Application.ThreadException can be used to handle these
if you run Forms on other threads than the main thread you will need to set Application.ThreadException from each such thread
I am catching exceptions globally and it's working fine except for the part that application doesn't resume on UnhandledExceptions.
I have read on MSDN that in order to allow dispatcher Exception to catch unhandled non UI exceptions, I need to do following two things, but I have no idea how to do that.
Dispatch those exceptions to the main UI thread.
Rethrow them on the main UI thread without handling them to allow DispatcherUnhandledException to be raised.
My code:
public partial class App : Application
{
public App()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Dispatcher Exception", MessageBoxButton.OK, MessageBoxImage.Warning);
e.Handled = true;
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
MessageBox.Show(ex.Message, "Unhandeled Exception Event", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
Don' know if this will help but to dispatch to the main UI thread you will need to call Invoke.
e.g. some sudo code if you are on the main form.
try
{
... stuff
}
catch(Exception ex)
{
this.Invoke(()=> throw ex));
}
If you are not on the main form then you will need to throw an event from where ever the error occurs and have something listening on the main form and then do the above in the method attached to the listener.
From the MSDN:
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.
(emphasize added)
So the UnhandledException event is only provided for logging information etc. It doesn't prevent the shutdown of the application.
However in Windows.Forms application you may consider this (same MSDN artice, scroll down):
In applications that use Windows Forms, unhandled exceptions in the
main application thread cause the Application.ThreadException event to
be raised. If this event is handled, the default behavior is that the
unhandled exception does not terminate the application, although the
application is left in an unknown state.
(emphasize added).
It worked fine for me
/// <summary>
/// All Application Exception is Handled by this Event
/// </summary>
/// <param name="sender">Error Object</param>
/// <param name="e">Error value</param>
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
try
{
try
{
e.Handled = true;
WpfLogger.Log.Error(e.Exception.ToString());
}
catch (Exception)
{
}
}
catch (Exception)
{
}
}
Question: I want to define a global exception handler for unhandled exceptions in my console application. In asp.net, one can define one in global.asax, and in windows applications /services, one can define as below
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyExceptionHandler);
But how can I define a global exception handler for a console application ?
currentDomain seems not to work (.NET 2.0) ?
Edit:
Argh, stupid mistake.
In VB.NET, one needs to add the "AddHandler" keyword in front of currentDomain, or else one doesn't see the UnhandledException event in IntelliSense...
That's because the VB.NET and C# compilers treat event handling differently.
No, that's the correct way to do it. This worked exactly as it should, something you can work from perhaps:
using System;
class Program {
static void Main(string[] args) {
System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
throw new Exception("Kaboom");
}
static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) {
Console.WriteLine(e.ExceptionObject.ToString());
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
Environment.Exit(1);
}
}
Do keep in mind that you cannot catch type and file load exceptions generated by the jitter this way. They happen before your Main() method starts running. Catching those requires delaying the jitter, move the risky code into another method and apply the [MethodImpl(MethodImplOptions.NoInlining)] attribute to it.
If you have a single-threaded application, you can use a simple try/catch in the Main function, however, this does not cover exceptions that may be thrown outside of the Main function, on other threads, for example (as noted in other comments). This code demonstrates how an exception can cause the application to terminate even though you tried to handle it in Main (notice how the program exits gracefully if you press enter and allow the application to exit gracefully before the exception occurs, but if you let it run, it terminates quite unhappily):
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void DemoThread()
{
for(int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
You can receive notification of when another thread throws an exception to perform some clean up before the application exits, but as far as I can tell, you cannot, from a console application, force the application to continue running if you do not handle the exception on the thread from which it is thrown without using some obscure compatibility options to make the application behave like it would have with .NET 1.x. This code demonstrates how the main thread can be notified of exceptions coming from other threads, but will still terminate unhappily:
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Notified of a thread exception... application is terminating.");
}
static void DemoThread()
{
for(int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
So in my opinion, the cleanest way to handle it in a console application is to ensure that every thread has an exception handler at the root level:
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void DemoThread()
{
try
{
for (int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception on the other thread");
}
}
You also need to handle exceptions from threads:
static void Main(string[] args) {
Application.ThreadException += MYThreadHandler;
}
private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e)
{
Console.WriteLine(e.Exception.StackTrace);
}
Whoop, sorry that was for winforms, for any threads you're using in a console application you will have to enclose in a try/catch block. Background threads that encounter unhandled exceptions do not cause the application to end.
I just inherited an old VB.NET console application and needed to set up a Global Exception Handler. Since this question mentions VB.NET a few times and is tagged with VB.NET, but all the other answers here are in C#, I thought I would add the exact syntax for a VB.NET application as well.
Public Sub Main()
REM Set up Global Unhandled Exception Handler.
AddHandler System.AppDomain.CurrentDomain.UnhandledException, AddressOf MyUnhandledExceptionEvent
REM Do other stuff
End Sub
Public Sub MyUnhandledExceptionEvent(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
REM Log Exception here and do whatever else is needed
End Sub
I used the REM comment marker instead of the single quote here because Stack Overflow seemed to handle the syntax highlighting a bit better with REM.
What you are trying should work according to the MSDN doc's for .Net 2.0. You could also try a try/catch right in main around your entry point for the console app.
static void Main(string[] args)
{
try
{
// Start Working
}
catch (Exception ex)
{
// Output/Log Exception
}
finally
{
// Clean Up If Needed
}
}
And now your catch will handle anything not caught (in the main thread). It can be graceful and even restart where it was if you want, or you can just let the app die and log the exception. You woul add a finally if you wanted to do any clean up. Each thread will require its own high level exception handling similar to the main.
Edited to clarify the point about threads as pointed out by BlueMonkMN and shown in detail in his answer.
Our core application is built in MFC C++, but we are trying to write new code in .NET, and have created a User Control in .NET, which will be used on an existing MFC Dialog.
However, when a unexpected/unhandled exception is thrown from the User Control, it causes the MFC app to crash (illegal op style), with no ability to recover.
I've added
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
To the Constructor of the .NET user control, but it doesn't seem to catch anything.
Is there any way to add an event in MFC to handle these?
Quick google didn't return anything useful.
Thanks.
Edit: Still haven't been able to resolve this the way I'd like, looks like the best way to do it, is try and catch around all the .NET code, so no exceptions bubble up.
I asked this same question a while ago: Final managed exception handler in a mixed native/managed executable?
What I have found is that the managed unhandled exception events ONLY fire when running in a managed thread. The managed WndProc is where the magic happens.
You have a few options: you could place a low-level override in CWinApp and catch Exception^. This could have unintended side-effects. Or, you could go with Structured Exception Handling (SEH) which will give you a hack at /all/ unhandled exceptions. This is not an easy road.
I think you want to have the unhandled exception handler in the MFC side of things:
AppDomain::CurrentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(&CurrentDomain_UnhandledException);
[same for Application.ThreadException]
Have a look at this similar question on the MSDN forums: Unhandled Exception in Mixed Mode application
Of course, the better idea would be either to handle the exception in the C# code, or else to find out what's causing it, and fix it so that the exception is never thrown. What's preventing that?
In every event handler of the user control, place a try/catch block:
private void btnOk_Click(object sender, EventArgs e) {
try {
// real code here
}
catch (Exception ex) {
LogException(ex);
// do whatever you must in order to shut down the control, maybe just
}
}
Here's what I use:
public static class UI
{
public static void PerformUIAction(Control form, Action action)
{
PerformUIAction(form, action, (string) null);
}
public static void PerformUIAction(
Control form, Action action, string message)
{
PerformUIAction(form, action, () => message);
}
public static void PerformUIAction(
Control form, Action action, Func<string> messageHandler)
{
var saveCursor = form.Cursor;
form.Cursor = Cursors.WaitCursor;
try
{
action();
}
catch (Exception ex)
{
MessageBox.Show(
messageHandler() ?? ex.Message, "Exception!",
MessageBoxButtons.OK, MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1,
MessageBoxOptions.DefaultDesktopOnly);
Debug.WriteLine(ex.ToString(), "Exception");
throw;
}
finally
{
form.Cursor = saveCursor;
}
}
}
I call it like this:
private void _copyButton_Click(object sender, EventArgs e)
{
UI.PerformUIAction(
this, () =>
{
// Your code here
});
}
I added the unhandled exception handler to the constructor of the .NET user control
I don't think that will work; I believe the exception handler has to be setup before a call to Application.Run. Do you have any Application.Run calls in your app?
How about something like this on the MFC side of things before you initialize any .NET controls:
Application.SetUnhandledExceptionMode(System.Windows.Forms.UnhandledExceptionMode.CatchException);
Application.ThreadException += ...;
See if the ThreadException handler is called.