Catch completely unexpected error - c#

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();
}
}

Related

Gracefully handling corrupted state exceptions

Related to this question, I would like to force CLR to let my .NET 4.5.2 app catch Corrupted State Exceptions, for the sole purpose of logging them and then terminating the application. What's the correct way to do this, if I have catch (Exception ex) at several places around the app?
So, after I specify the <legacyCorruptedStateExceptionsPolicy> attribute, if I understood correctly, all the catch (Exception ex) handlers will catch exceptions like AccessViolationException and happily continue.
Yeah, I know catch (Exception ex) is a Bad Idea™, but if CLR would at least put the correct stack trace into the Event Log, I would be more than happy to explain to the customer that his server app failing fast at 1AM and being offline for the night is a good thing. But unfortunately, CLR logs an unrelated exception into the Event Log and then closes the process so that I cannot find out what actually happened.
The question is, how to make this happen, process wide:
if the exception thrown is a Corrupted State Exception:
- write the message to the log file
- end the process
(Update)
In other words, this would probably work for most exceptions in a simple app:
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
static void Main() // main entry point
{
try
{
}
catch (Exception ex)
{
// this will catch CSEs
}
}
But, it won't work for:
Unhandled app domain exceptions (i.e. thrown on non-foreground threads)
Windows Service apps (which don't have an actual Main entry point)
So it seems like <legacyCorruptedStateExceptionsPolicy> is the only way to make this work, in which case I don't know how to fail after logging the CSE?
Instead of using <legacyCorruptedStateExceptionsPolicy> it would be better to use [HandleProcessCorruptedStateExceptions] (and [SecurityCritical]) as stated here:
https://msdn.microsoft.com/en-us/magazine/dd419661.aspx
Following that, your Main method should look something like this:
[HandleProcessCorruptedStateExceptions, SecurityCritical]
static void Main(string[] args)
{
try
{
...
}
catch (Exception ex)
{
// Log the CSE.
}
}
But be aware that this doesn't catch the more serious exceptions like StackOverflowException and ExecutionEngineException.
Also finally of involved try blocks will not be executed:
https://csharp.2000things.com/2013/08/30/920-a-finally-block-is-not-executed-when-a-corrupted-state-exception-occurs/
For other unhandled appdomain exceptions you can use :
AppDomain.CurrentDomain.UnhandledException
Application.Current.DispatcherUnhandledException
TaskScheduler.UnobservedTaskException
(Please do a search for the details when a specific handler is appropriate for your situation. TaskScheduler.UnobservedTaskException for example is a bit tricky.)
If you don't have access to the Main method, you can also mark your AppDomain exception handler to catch the CSE:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
...
[HandleProcessCorruptedStateExceptions, SecurityCritical]
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// AccessViolationExceptions will get caught here but you cannot stop
// the termination of the process if e.IsTerminating is true.
}
The last line of defense could be an unmanaged UnhandledExceptionFilter like this:
[DllImport("kernel32"), SuppressUnmanagedCodeSecurity]
private static extern int SetUnhandledExceptionFilter(Callback cb);
// This has to be an own non generic delegate because generic delegates cannot be marshalled to unmanaged code.
private delegate uint Callback(IntPtr ptrToExceptionInfo);
And then somewhere at the beginning of your process:
SetUnhandledExceptionFilter(ptrToExceptionInfo =>
{
var errorCode = "0x" + Marshal.GetExceptionCode().ToString("x2");
...
return 1;
});
You can find more information about the possible return codes here:
https://msdn.microsoft.com/en-us/library/ms680634(VS.85).aspx
A "specialty" of the UnhandledExceptionFilter is that it isn't called if a debugger is attached. (At least not in my case of having a WPF app.) So be aware of that.
If you set all the appropriate ExceptionHandlers from above, you should be logging all exceptions that can be logged. For the more serious exceptions (like StackOverflowException and ExecutionEngineException) you have to find another way because the whole process is unusable after they happened. A possible way could perhaps be another process that watches the main process and logs any fatal errors.
Additional hints:
In the AppDomain.CurrentDomain.UnhandledException you can safely cast the e.ExceptionObject to Exception without having to worry - at least if you don't have any IL code that throws other objects than Exception: Why is UnhandledExceptionEventArgs.ExceptionObject an object and not an Exception?
If you want to suppress the Windows Error Reporting dialog, you can take a look here: How to terminate a program when it crashes? (which should just fail a unit test instead of getting stuck forever)
If you have a WPF application with multiple dispatchers you can also use a Dispatcher.UnhandledException for the other dispatchers.
Thanks to #haindl for pointing out that you can also decorate handler methods with the [HandleProcessCorruptedStateExceptions]1 attribute, so I made a little test app just to confirm if things really work as they are supposed to.
1 Note: Most answers state that I should also include the [SecurityCritical] attribute, although in the tests below omitting it didn't change the behavior (the [HandleProcessCorruptedStateExceptions] alone seemed to work just fine). However, I will leave both attributes below since I am presuming all these folks knew what they were saying. That's a school example of "Copied from StackOverflow" pattern in action.
The idea is, obviously, to remove the <legacyCorruptedStateExceptionsPolicy> setting from app.config, i.e. only allow our outermost (entry-level) handler(s) to catch the exception, log it, and then fail. Adding the setting will allow your app to continue, if you catch the exception in some inner handler, and this is not what you want: the idea is just to get the accurate exception info and then die miserably.
I used the following method to throw the exception:
static void DoSomeAccessViolation()
{
// if you have any questions about why this throws,
// the answer is "42", of course
var ptr = new IntPtr(42);
Marshal.StructureToPtr(42, ptr, true);
}
1. Catching exceptions from Main:
[SecurityCritical]
[HandleProcessCorruptedStateExceptions]
static void Main(string[] args)
{
try
{
DoSomeAccessViolation();
}
catch (Exception ex)
{
// this will catch all CSEs in the main thread
Log(ex);
}
}
2. Catching all exceptions, including background threads/tasks:
// no need to add attributes here
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
// throw on a background thread
var t = new Task(DoSomeAccessViolation);
t.Start();
t.Wait();
}
// but it's important that this method is marked
[SecurityCritical]
[HandleProcessCorruptedStateExceptions]
private static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// this will catch all unhandled exceptions, including CSEs
Log(e.ExceptionObject as Exception);
}
I would recommend using just the latter approach, and removing the [HandleProcessCorruptedStateExceptions] from all other places to make sure the exception doesn't get caught at the wrong place. I.e. if you have a try/catch block somewhere and an AccessViolationException is thrown, you want CLR to skip the catch block and propagate to the UnhandledException before ending the app.
Is party over? not so fast
Microsoft: "Use application domains to isolate tasks that might bring down a process."
The program below will protect your main application/thread from unrecoverable failures without risks associated with use of HandleProcessCorruptedStateExceptions and <legacyCorruptedStateExceptionsPolicy>
public class BoundaryLessExecHelper : MarshalByRefObject
{
public void DoSomething(MethodParams parms, Action action)
{
if (action != null)
action();
parms.BeenThere = true; // example of return value
}
}
public struct MethodParams
{
public bool BeenThere { get; set; }
}
class Program
{
static void InvokeCse()
{
IntPtr ptr = new IntPtr(123);
System.Runtime.InteropServices.Marshal.StructureToPtr(123, ptr, true);
}
// This is a plain code that will prove that CSE is thrown and not handled
// this method is not a solution. Solution is below
private static void ExecInThisDomain()
{
try
{
var o = new BoundaryLessExecHelper();
var p = new MethodParams() { BeenThere = false };
Console.WriteLine("Before call");
o.DoSomething(p, CausesAccessViolation);
Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); //never stops here
}
catch (Exception exc)
{
Console.WriteLine($"CSE: {exc.ToString()}");
}
Console.ReadLine();
}
// This is a solution for CSE not to break your app.
private static void ExecInAnotherDomain()
{
AppDomain dom = null;
try
{
dom = AppDomain.CreateDomain("newDomain");
var p = new MethodParams() { BeenThere = false };
var o = (BoundaryLessExecHelper)dom.CreateInstanceAndUnwrap(typeof(BoundaryLessExecHelper).Assembly.FullName, typeof(BoundaryLessExecHelper).FullName);
Console.WriteLine("Before call");
o.DoSomething(p, CausesAccessViolation);
Console.WriteLine("After call. param been there? : " + p.BeenThere.ToString()); // never gets to here
}
catch (Exception exc)
{
Console.WriteLine($"CSE: {exc.ToString()}");
}
finally
{
AppDomain.Unload(dom);
}
Console.ReadLine();
}
static void Main(string[] args)
{
ExecInAnotherDomain(); // this will not break app
ExecInThisDomain(); // this will
}
}

How to notify an exception in C#?

I have an exception occurred when the Database connection failed in a Class. The problem is how do I notify my Main Window that this exception is caught and show a message box to notify my user?
Thanks
Use the Try ... Catch clause like this:
try
{
// The code that could generate an exception
}
catch(Exception ex)
{
MessageBox.Show("Error: " ex.Message);
}
Or if you're using SQL-Server connection, use it like this:
try
{
// The code that could generate an exception
}
catch(SqlException ex)
{
MessageBox.Show("SQL Error: " ex.Message);
}
Thanks. I may have not make my question clearly. I mean this exception
is occurred in one class, but the message box should be show in an
other windows class. So how do I communicate and show this error?
From your clarification in one of the comments:
So if you have class TestClass.cs with method Test in it.
public void Test()
{
//if you want to throw an exception defined by your business logic
if(someCondition == false)
throw CustomException();
//if you have exception in the code
int a = 5;
int b =0;
//here you will be thrown an exception can't divide by 0.
int c = a/b;
}
Your winform Button Click or whatever
public void Button_Click1(object sender, EventArgs e)
{
try
{
TestClass cl = new TestClass();
cl.Test();
}
catch(CustomException custEx)
{
//this for your Bussines logic exception
//write your message
}
catch(DivideByZeroException div)
{
//this for divide by zero exception
//write message
}
//you can catch all other exception like this but I don't advice you to do that
catch(Exception ex)
{
//for this to working properly, this catch should be under all of others(last priority)
}
}

Exception Unhandled by User Code

I have a member of a library being declared on the main page of my app:
private OpticalReaderLib.OpticalReaderTask _task = new OpticalReaderLib.OpticalReaderTask();
It works fine until I want to navigate back to this page at a different time. It brings up the error "An exception of type 'System.Exception' occurred in OpticalReaderLib.DLL but was not handled in user code".
Does anyone know why this is happening?
Thanks.
System.Exception is the base class for all Exceptions, so this is a very generic error message.
You could try logging more detail (e.g. exception.Message or exception.InnerException) about the exception that is thrown as part of your investigation. (via a try-catch statement).
It looks like you're initialising a field, where is this code being executed?
Update due to comment
As a temporary solution to discover the exception error.
private OpticalReaderLib.OpticalReaderTask _tempTask;
private OpticalReaderLib.OpticalReaderTask _task
{
get
{
//code to debug the error that is occuring
try
{
if (_tempTask == null)
_tempTask = new OpticalReaderLib.OpticalReaderTask();
else
return _tempTask;
}
catch (Exception exception)
{
//Log the exception detail here
}
}
}
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (_task != null)
{
_task.Completed -= OpticalReaderTask_Completed;
_task.Dispose();
_task = null;
}
base.OnBackKeyPress(e);
}

Creating an error message that reports a crash from anywhere inside an C# application

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.

What happen if the code within a catch fails

Using c# code within a web application, I have a try catch statement in my code and within the catch I want to do several things such as email an administrator.
I am wondering what would happen if the email code or other code within the catch fails? Is there a way to handle a general exception in the application?
Description
There are 2 things you can do to catch unhandled exceptions. Application.ThreadException and AppDomain.CurrentDomain.UnhandledException
Application.ThreadException Occurs when an untrapped thread exception is thrown.
AppDomain.CurrentDomain.UnhandledException Occurs when an exception is not caught.
Handle a exception inside the catch block.
Sample
Application.ThreadException and AppDomain.CurrentDomain.UnhandledException
Application.ThreadException +=
new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Handle a exception inside the catch block.
try
{
// do something
}
catch (Exception ex)
{
try
{
// send E-Mail
}
catch
{
// handle
}
}
More Information
Application.ThreadException Event
AppDomain.UnhandledException Event
If an exception is thrown within the catch clause, it simply raises another exception. One way to solve it is to simply have a nested try, eg.
try {
<stuff>
} catch(Exception e) {
try {
<email admin>
catch(EmailException e2) {
<stuff>
}
<stuff>
}
One approach is to handle the exception within the catch statement:
try
{
// Do stuff
}
catch (SpecificException ex)
{
try
{
// Try e-mailing
}
catch (AnotherException ex1)
{
// Write local log file
}
}
this will allow the program to continue.
However, if the program can't you can handle all unhandled exceptions at the application level and do something there.
Sure, you will have to surround the routine where you have your try catch with another try catch, or write your code in the catch statement surrounded with a try catch statement.
you can try aplication exception, if it's fatal error. , though its become obsolete Checkthis now in .net framework.
Application exceptions
public sealed class Product
{
private String name;
public String Name
{
get { return name; }
set
{
if (value != null) name = value;
else throw new UndefinedNameException();
}
}
public sealed class UndefinedNameException : ApplicationException
{
public UndefinedNameException() : base("Name cannot be null") {}
}
} // end of class Product
If the exception is thrown in catch block it will be propagated the normal way exceptions are.
You will need the following code:
try
{
//code
}
catch (SomeKindOfError e1)
{
try
{
// send email
}
catch (EmailError e2)
{
}
}
Your exception would be caught by any outer block where it is eligible, e.g. if you have:
try
{
// ...
try {
//code
}
catch (SomeKindOfErrorThatIsNotEmailError e1)
{
// send email
}
// ...
}
catch
{
// your email exception will get caught here
}
I am wondering what would happen if the email code or other code within the catch fails?
The exception thrown within catch will be handled by CLR Default Handler if not enclosed within another try-catch pair.
However finally will definitely execute. so you can use it to clearing or closing the resources.
Is there a way to handle a general exception in the application?
within main method, write following code part:
try
{
// write normal code
}
catch(Exception e)
{
// if here exception occurs ... God Help.
}
this is for a windows application
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppDomain.CurrentDomain.UnhandledException += AppDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
}
static void Application_ThreadException(Object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Application.ThreadException");
}
static void AppDomain_UnhandledException(Object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(((Exception)e.ExceptionObject).Message, "AppDomain.UnhandledException");
}
There is no incompatibily with the fact to use a try catch sequence in a catch snippet
Logically, you won't catch the same exception so you can know what part failed
Lot of guys gave u the code to use, accept one of these answers

Categories

Resources