I have this code:
try
{
Application.Run(myForm);
}
catch (Exception e)
{
// handle
}
In my MyForm, when I throw an exception in a button click handler, it is caught as expected and handled by the above code. When I throw in the form's onEnter handler, it is not caught.
Use AppDomain.CurrentDomain.UnhandledException
public static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
Application.Run(myForm);
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception) args.ExceptionObject;
Console.WriteLine("MyHandler caught : " + e.Message);
Console.WriteLine("Runtime terminating: {0}", args.IsTerminating);
}
Related
This question has been answered a thousand times but although I've tried everything, I can't seem to get my Global Exception Handler to work.
I'm using a windows form with several async methods. All my async methods are wrapped in try catch blocks and handled accordingly. I also have every block of code where I expect an exception wrapped in a try catchblock.
I'm interested in using a global exception handler to catch exceptions that I'm not expecting so that I can log them and let the user know there has been an exception before safely closing down the program.
In Main() I have the following:
[STAThread]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
static void Main()
{
crashLogInit = InitLogExceptions(); // sets global exception handlers and returns true if successful.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainWindow = new MainWindow(); // My window
LoadSaveManager.Init(); // initiates all relavent components for saving and loading data.
if (isLoaded() && crashLogInit) // Loads data and checks it is successful, also checks global exception handlers are set.
{
RunProgram(); //Method which does Application.Run(MainWindow);
}
else
{
MessageBox.Show(Form.ActiveForm, "Error while starting application!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
CloseResources();
}
}
In the InitLogExceptions() I have the following:
private static bool InitLogExceptions()
{
try
{
crashlogPath = Path.Combine(Directory.GetCurrentDirectory(), crashlogName);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
return true;
}
catch { return false; }
}
In MainWindow() I have a button which fires a clicked event which throws an ArgumentNullException which is getting caught by the debbugers own exception handler but isnt getting caught by any of mine nor is it getting logged.
Below is the code for my exception handlers:
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
ShowException(sender, e.Exception, true);
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
ShowException(sender, e.ExceptionObject as Exception, true);
}
public static void ApplicationHandler(object sender, Exception e)
{
if (!crashLogInit) { InitLogExceptions(); }
ShowException(sender, e, false);
}
public static void ApplicationHandler(object sender, Exception e, bool forceClose)
{
if (!crashLogInit) { InitLogExceptions(); }
ShowException(sender, e, forceClose);
}
private static bool WriteToLog(object sender, Exception exception)
{
try
{
DateTime dateTime = DateTime.Now;
StreamWriter writer = File.AppendText(crashlogPath);
string date = dateTime.ToString("yyyy-MM-dd # HH:mm:ss");
writer.WriteLine(date + ":");
writer.WriteLine();
writer.WriteLine();
writer.Write($" SENDER: {sender.GetType().ToString()} EXCEPTION MESSAGE: {exception.Message}");
writer.WriteLine(exception.Source == null ? "" : $"SOURCE: {exception.Source}");
writer.WriteLine();
writer.WriteLine(exception.StackTrace == null ? exception.InnerException.StackTrace : exception.StackTrace);
if (exception.GetType().IsSubclassOf(typeof(AppExceptions)))
{
writer.WriteLine();
writer.WriteLine($"ORIGINAL MESSAGE: {exception.InnerException.Message} ORIGINAL SOURCE: {exception.InnerException.Source}");
}
writer.WriteLine();
writer.WriteLine();
writer.Close();
return true;
}
catch (Exception)
{
return false;
}
}
private static void ShowException(object sender, Exception e, bool forceClose)
{
StringBuilder output = new StringBuilder();
if (WriteToLog(sender, e))
{
output.AppendLine($"Copied to Crashlog! Location of Crashlog file: {crashlogPath}");
output.AppendLine();
output.AppendLine("Send Crashlog to developer!");
}
else
{
output.AppendLine("Could not copy to Crashlog!");
}
output.AppendLine();
output.AppendLine(forceClose ? "Application will now close!" : "Application will now continue at user's own risk!");
MessageBox.Show(Form.ActiveForm, output.ToString(), e.Message.ToUpper() + "!", MessageBoxButtons.OK, MessageBoxIcon.Error);
if (forceClose)
{
Environment.FailFast(e.Message, e);
}
}
Exceptions else where are working and getting logged except this simple thrown exception on a button clicked. What am I doing wrong?
I want to catch all unhandled exceptions in my application. so I used this code to catch all the unhandled exceptions:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
SaveEx(e.Exception);
Application.Exit();
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
SaveEx((Exception)e.ExceptionObject);
Application.Exit();
}
static void SaveEx(Exception ex)
{
bool exists = System.IO.Directory.Exists(Path.GetDirectoryName(#"C:\AppLogs\"));
if (!exists)
System.IO.Directory.CreateDirectory(Path.GetDirectoryName(#"C:\AppLogs\"));
String filePath = #"C:\AppLogs\" + DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss") + ".txt";
String log = "===========Start=============\r\n";
log += "Error Message: " + ex.Message + "\r\n";
log += "Stack Trace: " + ex.StackTrace + "\r\n";
log += "===========End=============";
System.IO.File.WriteAllText(filePath, log);
}
}
I tried to raise these exceptions with a divide in 0:
on main thread it's work perfect:
int t = 0;
int r = 5 / t;
But when i try to do it inside a Thread:
Thread thread = new Thread(delegate()
{
int t = 0;
int r = 5 / t;
});
thread.Start();
The CurrentDomain_UnhandledException function got called but it keeps calling the int r = 5 / t; row in my code so I have a loop of exceptions. Any idea what can be the problem? the thread is called only once.
You need to change Application UnhandledExceptionMode
to UnhandledExceptionMode.CatchException to make things works correctly. Microsoft already wrote a very good article about it here.
I tried to simulate your work. Everything worked well, take a look on my example.
[STAThread]
static void Main()
{
// 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 UI thread exceptions to the event.
Application.ThreadException += Application_ThreadException;
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Application_ThreadException");
Application.Exit();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
MessageBox.Show(exception.Message, "CurrentDomain_UnhandledException");
Application.Exit();
}
So, if we raise an exception inside a thread like below:
private void button1_Click(object sender, EventArgs e)
{
var thread = new Thread(delegate () {
throw new DivideByZeroException();
});
thread.Start();
}
button1_Click is fired.
thread get started and raises a DividedByZeroException.
CurrentDomain_UnhandledException catches the exception, shows the message and closes the app
I'm using AppDomain.CurrentDomain.UnhandledException to catch all the unhandled exceptions in my Xamarin.Droid project. But receiving null for Exception.StackTrace.
I have the following code inside a class which extends Application
//Inside constructor
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += HandleExceptions;
static void HandleExceptions(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception) args.ExceptionObject;
Console.WriteLine("MyHandler caught : " + e.Message);
Console.WriteLine("StackTrace: ", e.StackTrace);
}
What should I do to get the StackTrace of the exception?
I have been trying to log this exception for days but cant figure it out. So I thought I post it here with the hope that someone could help. I have also posted some of my code that I'm currently using to catch unhandled exceptions but the exception never showed up in the log file.
I would appreciate if someone could help me.
Problem Event Name: APPCRASH
Application Name: Myapp.exe
Application Version: 1.0.0.0
Application Timestamp: 52e9aab8
Fault Module Name: clr.dll
Fault Module Version: 4.0.30319.18052
Fault Module Timestamp: 5173c26b
Exception Code: c00000fd
Exception Offset: 00372b52
OS Version: 6.1.7601.2.1.0.272.7
Locale ID: 1033
Additional Information 1: 5cff
Additional Information 2: 5cfff2c5825852a6f100872ec6f038a2
Additional Information 3: a2a3
Additional Information 4: a2a3734c473189c5efabc88b5081d05a
public MainWindow()
{
Application.Current.DispatcherUnhandledException += CurrentOnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
Dispatcher.UnhandledException += DispatcherOnUnhandledException;
InitializeComponent();
}
private void DispatcherOnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.Exception;
using (StreamWriter writer = File.AppendText("ExceptionsLog.txt"))
{
DateTime time = DateTime.Now;
writer.WriteLine("Time {0} Exception: {1}", time, e);
writer.Flush();
}
args.Handled = true;
MessageBox.Show(e.ToString());
}
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
using (StreamWriter writer = File.AppendText("ExceptionsLog.txt"))
{
DateTime time = DateTime.Now;
writer.WriteLine("Time {0} Exception: {1} Runtime termination: {2}", time, e.Message, args.IsTerminating);
writer.Flush();
}
MessageBox.Show(e.ToString());
}
private void CurrentOnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.Exception;
using (StreamWriter writer = File.AppendText("ExceptionsLog.txt"))
{
DateTime time = DateTime.Now;
writer.WriteLine("Time {0} Exception: {1}", time, e);
writer.Flush();
}
args.Handled = true;
MessageBox.Show(e.ToString());
}
For handling unhandled exceptions, please create a method like this
protected TResult LogFailedOperations<TResult>(Func<TResult> action)
{
try
{
return action();
}
catch (Exception ex)
{
// Logic for logging from ex.Message
}
}
Also, when you perform any method, just enclose that method around this LogFailedOperations method like these examples -
private void MyButton_Click(object sender, RoutedEventArgs e)
{
var result = LogFailedOperations(() => { /* Your logic for button click */ });
}
private void LoadDataToView()
{
var result = LogFailedOperations(() => { /* Your logic for laoding data */ });
}
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
var result = LogFailedOperations(() => { /* Your logic for slider changed event */ });
}
I've really read all other similar threads on Stackoverflow. Nothing works for me...
I throw an exception of type "Exception" but i can't handle the exception.
I've tried it in the DoWork Progress, in the CompletedEvent (with try/catch, witch e.error....)
void bgGetResponse_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
ConvertByte(myFile);
myFile= null;
}
}
void bgGetResponse_DoWork(object sender, DoWorkEventArgs e)
{
byte[] test= new byte[] { 1, 1, 0, 1, 1};
//Here the error occured (just with throw new Exception("error"))
//The method only throws an exception (for test purposes)
testResponse= _configManager.GetResponse(test, 0);
}
GetResponse(...)
{
throw new Exception("..!");
}
Any ideas?
Thanks for your efforts
I usually just catch it in the work Method and set the result to it.
private void BGW_DoWork(object sender, DoWorkEventArgs e)
{
...
}
catch (Exception ex)
{
e.Result = ex;
}
Then look in the Completed event,
private void BGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Cursor = Cursors.Default;
try
{
Exception ex = e.Result as Exception;
if (null != ex)
throw ex;
...
If by "can't handle" the exception you mean can't use catch, that's true. You just use the Error property. You could "throw" that in your Completed event handler; but then you stack frame will be different.
e.g.:
try
{
if(e.Error != null) throw(e.Error)
// handle success case
}
catch(MyException exception)
{
// handle specific error.
}
Any unhandled exceptions occuring in the BackgroundWorkers DoWork function will cause the worker to fire RunWorkerCompleted where the event argument will contain the error.