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?
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 developing one WPF application, in which I've to handle Exception globally.
For that I've refer MSDN document.
And accordingly my code on my main window:
private void TestMethod()
{
string s = null;
try
{
s.Trim();
}
catch (Exception ex)
{
MessageBox.Show("A handled exception just occurred: " + ex.Message, "RestartApplication", MessageBoxButton.OK, MessageBoxImage.Warning);
}
s.Trim();
}
In my App.xaml.cs
public App() : base()
{
this.Dispatcher.UnhandledException += Application_DispatcherUnhandledException;
}
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show("An unhandled exception just occurred: " + e.Exception.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
e.Handled = true;
}
Here i expecting two MessageBoxfor an exception. and seems like Application_DispatcherUnhandledException not called.
But VS gives an error on second s.Trim();
How can i handle an error and show message box from App.xaml.cs?
I've refer many links of SO like: dispatcherunhandledexception-does-not-seem-to-work
globally-catch-exceptions-in-a-wpf-application
Update : Real time application code, were second message box not displaying :
private void ListProcesses()
{
string s = null;
Process[] localByName = Process.GetProcessesByName("notepad++");
DateTime test = new DateTime();
try
{
s.Trim();
foreach (Process p in localByName)
{
this.Dispatcher.Invoke(() =>
{
if (storevalue != p.MainWindowTitle && !String.IsNullOrEmpty(p.MainWindowTitle))
{
aTimer.Stop();
this.Visibility = Visibility.Visible;
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
this.Topmost = true;
this.WindowState = System.Windows.WindowState.Maximized;
this.ResizeMode = System.Windows.ResizeMode.NoResize;
storevalue = p.MainWindowTitle;
}
});
}
}
catch (Exception ex)
{
aTimer.Stop();
MessageBoxResult result = MessageBox.Show("A handled exception just occurred: " + ex.Message, "RestartApplication", MessageBoxButton.OK, MessageBoxImage.Warning);
}
s.Trim();
}
Erm..I think I know what is happening to you. The Dispatcher.UnhandledException event only works when the app is running, not when you run it from the Visual Studio. Try to run it from the Debug folder for example, and i think you'll see the expected behaviour.
When you run your app from Visual Studio, VS itself is handling the exception so it would never be unhandled, thus never firing the Dispatcher.UnhandledException event.
EDIT
Ok, after studying your code, i guess your ListProcesses method is running in a Timer. Timers does not pass the exceptions to the calling thread, so it would never work. If you are using System.Timers.Timer it will silently swallow exceptions and if you use System.Threading.Timer will terminate the program.
So in that case, you'll need to take care of the Exceptions yourself, sorry :)
Remove your try / catch blocks, and run "Start Without Debugging (Ctrl+F5)" .
Application.DispatcherUnhandledException Event
is fired only by unhandled exceptions.
This is what I did :
public partial class Window12 : Window
{
public Window12()
{
InitializeComponent();
string id = null;
id.Trim();
}
}
App.xaml.cs
public partial class App : Application
{
public App()
{
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
}
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show("Unhandled exception occured > " + e.Exception.ToString());
}
}
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);
}
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 */ });
}