In my App.xaml.cs, I have these codes to catch the exceptions and log them
public App()
{
SetupExceptionHandlingInApp();
// other codes
}
private void SetupExceptionHandlingInApp()
{
this.DispatcherUnhandledException += (s, e) =>
{
e.Handled = true;
//LOGGING CODE HERE
this.Shutdown(-1);
};
}
[STAThread]
public static void Main()
{
SetupExceptionHandlingInMain();
//other codes
}
private static void SetupExceptionHandlingInMain()
{
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
{
//LOGGING CODE HERE
Environment.Exit(1);
};
System.Windows.Forms.Application.ThreadException += (s, e) =>
{
//LOGGING CODE HERE
Environment.Exit(1);
};
TaskScheduler.UnobservedTaskException += (s, e) =>
{
//LOGGING CODE HERE
};
}
Almost cases, I can catch the exception and log it. But the application crashes sometimes while execution, and I can't find an error logged about the exception that caused the crash.
Am I missing a method besides the methods above to catch the exception? I looked at some article on SO but almost them used these methods above.
The log4net works well because I can see all ERROR and INFO log.
EDIT
After following the suggestion of Panagiotis Kanavos, I found out the error:
Application : xxx.exe
Version du Framework : v4.0.30319
Description : le processus a été arrêté en raison d'une erreur interne dans le runtime .NET à l'adresse IP 547541C4 (54380000) avec le code de sortie 80131506.
TRANSLATE
Application: xxx.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an internal error in
the .NET Runtime at IP 547541C4 (54380000) with exit code 80131506.
Perhaps you got an exception that corrupted the state of the process? From the documentation:
Starting with the .NET Framework 4, this event is not raised for
exceptions that corrupt the state of the process, such as stack
overflows or access violations, unless the event handler is
security-critical and has the
HandleProcessCorruptedStateExceptionsAttribute attribute.
Perhaps you can temporarily specify that your handler is security-critical to be able to catch the exception during debugging.
Related
I came across a problem that is the AccessViolationException was unhandled after i run my program for about a day long.
(More information: I am using Visual Studio 2010)
However, it does not state where this exception occurs, there were two options given to me which is "ok" and "continue". When i pressed ok, nothing happened so i pressed continue and the program stops debugging.
When i tried to find a solution, i understand that i can implement HandleProcessCorruptedStateExceptions to fix this problem. However, i have no clue where to start.
Do i simply include the codes below only? And where do i include these code?
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public static int Main()
{
try
{
// Catch any exceptions leaking out of the program CallMainProgramLoop();
}
catch (Exception e)
// We could be catching anything here
{
// The exception we caught could have been a program error
// or something much more serious. Regardless, we know that
// something is not right. We'll just output the exception
// and exit with an error. We won't try to do any work when
// the program or process is in an unknown state!
System.Console.WriteLine(e.Message);
return 1;
}
return 0;
}
Alternatively, i can also do this legacyCorruptedStateExceptionsPolicy but it says that i should input the required statement in the config file. Where can i find the config file?
Appreciate all the replies!
The actual answer for you question is here and I really shouldn't answer it again, but I want to show you some code sample and I don't want to write it in comment :)
In one of my projects from time to time there was an unpredictable exception. To catch it I write this code in Program.cs:
[STAThread]
static void Main()
{
// add UnhandledException handler
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
// prepare message for user
var message = "There was an unknown exception while running <app_name>!";
var exception = e.ExceptionObject as Exception;
if (exception != null)
{
// change message if there was actual exception
message = $"There was an {exception.GetType().Name} exception while running <app_name>! {exception.Message}";
// adding inner exceptions messages
var innerException = exception.InnerException;
while (innerException != null)
{
message += $"\r\n-> {innerException.GetType().Name}: {innerException.Message}";
innerException = innerException.InnerException;
}
#if DEBUG
// add tracing info
message += $"\r\n\r\n{GetStackTrace(exception)}";
#endif
}
if (e.IsTerminating) message += "\r\n\r\n<app_name> will be closed.";
// showing message to the user
MessageBox.Show(message, "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
#if DEBUG
private static string GetStackTrace(Exception exception)
{
var trace = new System.Diagnostics.StackTrace(exception, fNeedFileInfo: true);
var frames = trace.GetFrames()
.Select((f, i) => {
var filename = f.GetFileName();
var methodInfo = f.GetMethod();
var frame = $"#{i} in the method {methodInfo.DeclaringType.FullName}.{methodInfo.Name}()";
if (filename != null) frame += $" (source file: {System.IO.Path.GetFileName(filename)}#{f.GetFileLineNumber()}:{f.GetFileColumnNumber()})";
return frame;
});
return $"Full stack trace ({trace.FrameCount} frames total):\r\n{string.Join("\r\n", frames)}";
}
#endif
Now, when unhandled exception occurring - there will be a message box, that shows full exception message (and inner exceptions messages). There was also a full stack trace for Debug build with method name, line number and source filename where exception occure.
About HandleProcessCorruptedStateExceptions
You mention a HandleProcessCorruptedStateExceptions attribute in your comment. The docs clearly says that you shouldn't use it unless you absolutely sure that you need it.
Corrupted process state exceptions are exceptions that indicate that
the state of a process has been corrupted. We do not recommend
executing your application in this state.
By default, the common language runtime (CLR) does not deliver these
exceptions to managed code, and the try/catch blocks (and other
exception-handling clauses) are not invoked for them. If you are
absolutely sure that you want to maintain your handling of these
exceptions, you must apply the
HandleProcessCorruptedStateExceptionsAttribute attribute to the method
whose exception-handling clauses you want to execute. The CLR delivers
the corrupted process state exception to applicable exception clauses
only in methods that have both the
HandleProcessCorruptedStateExceptionsAttribute and
SecurityCriticalAttribute attributes.
Corrupted process state means that some really catastrophic things happens and it safer for your app to die right now. If you are still not scared enough, here is the Main() method from the example above with the HandleProcessCorruptedStateExceptions attribute set:
[STAThread]
[HandleProcessCorruptedStateExceptions, SecurityCritical]
static void Main()
{
try
{
// add UnhandledException handler
// AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
// * in this particular case is not quite useful to handle this exceptions,
// because you already wrap your entire application in a try/catch block
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
catch (Exception ex)
{
// handle it somehow
}
}
Simplification — I've created an empty AWS Lambda project with .net CORE :
This is the default empty lambda function project :
I want to catch all exception in the app , globally.
So I've created a method that generates an exception, and added a global application handler :
Complete code :
public class Function
{
void CreateException()
{
var z = 0;
var a = 2 / z;
Console.Write(a);
}
public Function()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
public void FunctionHandler(object input, ILambdaContext context)
{
CreateException();
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// � It never gets here
}
}
The problem is that the exception is raised , but it never fires CurrentDomain_UnhandledException
Question:
Is this the right way of catching global exceptions ? and why doesn't CurrentDomain_UnhandledException invoked when there is an unhandled exception ?
While I cannot answer why this isn't working, I can tell you I have done as a workaround.
The workaround I have used is to wrap my FunctionHandler in a try/catch. Since this is the only entrypoint in the lambda function, anything that gets thrown in here will be caught...effectively acting like a global handler for my purposes.
public void FunctionHandler(object input, ILambdaContext context)
{
try
{
CreateException();
}
catch (Exception e)
{
// Handle your 'uncaught' exceptions here and/or rethrow if needed
Console.WriteLine(e);
throw;
}
}
You would likely want to rethrow so that:
AWS will retry the function again, then you can send it DeadLetterQueue after X retries
You get the exception in your CloudWatch Logs
I have an executable that is written in C# which runs fine on one computer but crashes without providing an error on another computer.
Is there a class that I can add to my code that will dump all the information relating to the crash no matter where the error occurs within the code?
I have seen this post but I was hoping to create a "catch all" error handling class that would exist in my code.
Try the AppDomain exception handler:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
Code sample:
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
var thr = new Thread(() =>
{
Thread.Sleep(1000);
throw new Exception("Custom exception from thread");
});
thr.Start();
thr.Join();
Console.WriteLine("Done");
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//Log information from e.ExceptionObject here
}
}
In this example a custom global exception handler is registered, and then a thread is started which throws an exception after 1 second. The global exception handler is then invoked, with the custom exception that has been thrown.
There are plenty of topics covering the question. But nevertheless I have a problem.
I load the assembly into new AppDomain like this:
public void Run()
{
//There's the problem.
//As Panos Rontogiannis mentioned the thread is created in default AppDomain
new Thread(RunApp).Start();
}
private void RunApp()
try
{
AppDomain.CreateDomain("domain name").ExecuteAssembly("path to assembly");
}
catch (Exception _e)
{
MessageBox.Show("Unhandled Exception.\n" + _e);
}
}
In the Main method of the loaded assembly I subscribe my handler to the UnhandledException event:
AppDomain.CurrentDomain.UnhandledException += handleException;
The handler itself:
public static void handleException(object a_s, UnhandledExceptionEventArgs a_args)
{
var _e = (Exception)a_args.ExceptionObject;
//Static loger class method
Loger.WriteError(_e.GetType().ToString(), _e.Message, "default solution");
}
But wherever the exception is thrown in the loaded assembly the handler doesn't get involved. I only catch exception in the default AppDomain (first try{} catch{}).
Most probably, the reason you cannot handle the exception in the new AppDomain is that it is not thrown from a thread that was created in that AppDomain. From the documentation on AppDomain.UnhandledException it is not very straight-forward to see that. The interesting part is the following:
An exception is unhandled only if the entire stack for the thread has
been unwound without finding an applicable exception handler, so the
first place the event can be raised is in the application domain where
the thread originated.
Now if the thread that executes the code that throws, is created in your main AppDomain (like the main thread of a console app), then you should add a handler in the main AppDomain. Note though that if the type of the thrown exception is not loaded in the main AppDomain, the Assembly Loader of .NET will try to load it from your applications' base directory and probing paths. If these are not the same with the child AppDomain, then the assembly will not be resolved and an(other) exception will be thrown.
There are a variety of reasons that this might happen. The event documentation at http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx covers quite a bit of this complexity in detail If nothing there seems applicable, could you please post repro code?
My guess is the handler is not invoked as the exception is handled. i.e. By the upper try{}catch{}.
I didn't realy understand why the handler doesn't get invoked.
I ended up using FirstChanceException instead of UnhandledException in Main method of loaded assembly. Like this:
AppDomain.CurrentDomain.FirstChanceException +=
(obj, e) => Loger.WriteError(
e.Exception.ToString(),
e.Exception.Message,
"default solution"
);
This is a late reply, but this seems to work fine if you ask me (VS2012/.NET 4.5), exception handler needs to be registered before ExecuteAssembly is called of course: (I have a child process that causes an Access Violation by writing to a null ref (unsafe code) just to force a crash and it triggers the HandleException below:
public static void HandleException(object a_s, UnhandledExceptionEventArgs a_args)
{
var _e = (Exception)a_args.ExceptionObject;
Console.WriteLine(_e.GetType().ToString(), _e.Message, "default solution");
}
public void StarProcessWithinAppDomain(string fileName)
{
try
{
// New appdoamin / check exception isolation level
AppDomain sandBox = AppDomain.CreateDomain("sandBox");
try
{
AppDomain.CurrentDomain.UnhandledException += HandleException;
sandBox.ExecuteAssembly(fileName);
}
catch (Exception ex)
{
Console.WriteLine("An error occurred (inner) within AppDomain, executing \"{0}\":" + "\n" + ex.Message, fileName);
}
finally
{
AppDomain.Unload(sandBox);
}
}
catch (Exception ex)
{
Console.WriteLine("An error occurred within AppDomain, executing \"{0}\":" + "\n" + ex.Message, fileName);
}
}
FirstChanceException fires.
Any catch blocks are executed.
If no catch block or throw in the block then UnhandledException fires
Your catch block ensures that UnhandledException doesn't fire.
I have a ErrorRecorder App, which prints the error report out and asks if the user wants to send that report to me.
Then, I have the main app. If an error occurs, It writes the error report to a file and asks ErrorRecorder to open that file to show user the error report.
So I am catching most of my errors using Try/Catch.
However, what if an error occurs that was completely unexpected and it shuts down my program.
Is there like an Global/Override method or something of that kind, that tells the program "Before shutting down if an unexpected error occurs, call the "ErrorRecorderView()" Method"
i think this is what you're after - you can handle exceptions at the appdomain level - i.e. across the whole program.
http://msdn.microsoft.com/en-GB/library/system.appdomain.unhandledexception.aspx
using System;
using System.Security.Permissions;
public class Test
{
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
public static void Example()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
try
{
throw new Exception("1");
}
catch (Exception e)
{
Console.WriteLine("Catch clause caught : " + e.Message);
}
throw new Exception("2");
// Output:
// Catch clause caught : 1
// MyHandler caught : 2
}
static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Console.WriteLine("MyHandler caught : " + e.Message);
}
public static void Main()
{
Example();
}
}