I am very new to c# programming, so that in mind:
I have an in-memory data object with data I need to save the information when(if) my application were to crash OR closed. Is there a way to do this deterministically or reliably?
I have been looking at destructors
~MyObjectName(){}
finalizers and Dispose(),
but as far as I understand none of these will do reliably what I want?
Currently I am using the destructor, and it works when I am closing the program, but this doesn't mean it will work on crashing, or always.
Should I be looking at events as well?
There is no 100% reliable mechanism that you can use to save data (or do anything else for that matter) when a process (any process, not just a .Net process) terminates - most processes can be terminated at any point using the "End Process" option in the task manager, when this happens the process is immediately killed. As a more extreme example the power cord could be pulled out the back of the machine.
If its not 100% necessary that this data object be up-to-date and saved once the process is killed then the AppDomain.UnhandledException Event may suffice.
If its absolutely 100% necessary that this be the case then you need to be continuously saving this information as the process is running - there is absolutely no guarentee that you will get a chance to do it at a later date. This is how databases operate, no transaction returns until some record of the change has been recorded to disk in some format (e.g. a transaction log). This is what the D stands for in ACID.
I believe you are looking for catching unhandled exceptions? something like this:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new Form1());
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
// here you can log the exception ...
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
// here you can log the exception ...
}
This example shows how to manage all exceptions that haven't been
caught in the try-catch sections (in Windows Forms application).
The UnhandledException event handles uncaught exceptions thrown from
the main UI thread. The ThreadException event handles uncaught
exceptions thrown from non-UI threads.
You can achieve this with windbg.
Keep a breakpoint in zwterminateprocess method in windbg. This method will be called when your application exits.
when the breakpoint is reached , use !dumpheap -type MyObjectName to get the address of your object
Use !dumpobject "address of MyObjectName" to know the values inside the object
Related
I have a publisher, dispatcher, subscriber.
publisher publish event through dispatcher to subscriber.
subscriber is a com object embedded in S.exe can be callback from dispatcher.exe when specific event coming from publisher.exe.
I expect any exception inside the subscriber to terminate the S.exe.
I did my investigation:
task, with
configuration can terminate the main process. related article,
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=netframework-4.7.2
new a thread in my code, without any specific configuration can
also, any unhandled exception inside the thread can crash the main
process. related article,
https://learn.microsoft.com/en-us/dotnet/standard/threading/exceptions-in-managed-threads
two attributes of one thread: {isbackground, isThreadPoolThread}.
task is {true, true}
artificial thread is {true, false},
subscriber callback thread is {true, false}.
is there any other configuration, like , can set to control whether or not to crash the main process?
You can handle AppDomain.CurrentDomain.UnhandledException event in which you can get the current process by using Process.GetCurrentProcess() and kill that process so your exe will terminate.
Put this line Main() in Program.cs:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException
Then implement CurrentDomain_UnhandledException as below.
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var currentProcess = Process.GetCurrentProcess();
currentProcess.Kill();
}
This is just concept as per your problem statement. You can change it as per your need.
Any exception inside a COM was wrapped as a HRESULT return to it's client by RCW.
So, no way to crash the main process when the exception was thrown inside a COM thread.
The answer may be related with:
COM methods report errors by returning HRESULTs; .NET methods report them by throwing exceptions. The runtime handles the transition between the two. Each exception class in the .NET Framework maps to an HRESULT.
from https://learn.microsoft.com/en-us/dotnet/framework/interop/how-to-map-hresults-and-exceptions
and other helpful links:
https://learn.microsoft.com/en-us/dotnet/framework/interop/runtime-callable-wrapper
https://learn.microsoft.com/en-us/dotnet/framework/interop/com-callable-wrapper
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I continue running after an unhandled exception?
I've seen tons of similar questions and anwsers on SO, but not the same.
I'm handling all uncaught exception in main like this:
In Main I set following:
Application.ThreadException += new ThreadExceptionEventHandler(MainForm_UIThreadException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.Run(new MainForm());
If I run my programm in debugger, after the exception occured and I handled them in MainForm_UIThreadException or CurrentDomain_UnhandledException, the yellow debugger arrow points to the line, where this exception actually occured, so I can step over, which means (for me) that execution context isn't lost.
I know that I cant continue execution for unhandled exceptions, but this esception is actually handled, just somewhere else.
Is it possible to continue execution of current function?
Thank you
You don't. When you get an AppDomain unhandled exception, your app is
no longer in a stable state. Where exactly would you resume to? When
you've gotten to that point, your only option, with good reason, is to
exit. You could reasonably schedule yourself to run again to make sure
the app comes back, but a far better idea is to actually handle the
exception at its source and prevent it from being an
UnhandledException.
From: How do I continue running after an unhandled exception?
In a WinForms application, if you want to continue running, you need to handle exceptions in your UI event handlers.
For example:
private void saveButton_Click(object sender, EventArgs e)
{
try
{
... call BLL to save data
}
catch(Exception ex)
{
MessageBox.Show("Failed to save data");
}
}
Consider the following simple application: a windows form created by a "new C# windows application" sequence in VS that was modified in a following way:
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("An unexpected exception was caught.");
}
}
Form1.cs contains the following modifications:
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Error");
}
If I press F5 in IDE, then, as I expect, I see a message box saying that exception was caught and the application quits.
If I go to Debug(or Release)/bin and launch the executable, I see the standard "Unhandled exception" window, meaning that my exception handler doesn't work.
Obviously, that has something to do with exception being thrown from a different thread that Application.Run is called from. But the question remains - why the behavior differs depending on whether the application has been run from IDE or from command line?
What is the best practice to ensure that no exceptions remain unhandled in the application?
Normally Application.ThreadException will handle the exception in the Load event. You'll get the ThreadExceptionDialog that offers the Quit and Continue options.
But not when a debugger is attached. The catch clause in the message loop that displays the dialog is intentionally disabled in that case. That's necessary because it would be very difficult to trouble-shoot exceptions if that dialog pops up when you debug a program. Which this catcher no longer active, your catch clause in the Main() method now gets a shot at the exception.
You can make it consistent by using Application.SetUnhandledExceptionMode() in the Main() method. You shouldn't, exceptions really are hard to debug if you do this. If you want to customize exception handling for the UI thread then you should register your own Application.ThreadException handler:
if (!System.Diagnostics.Debugger.IsAttached)
Application.ThreadException += myThreadException;
Trapping unhandled exceptions in worker threads requires a AppDomain.UnhandledException handler. They are not recoverable.
Also beware of a bug in 64-bit Windows, exceptions in the Load event are swallowed without diagnostic when a debugger is attached. Force AnyCPU mode to avoid that trap.
In addition to catching any exceptions thrown inside the Main method you must also handle AppDomain.CurrentDomain.UnhandledException and Application.ThreadException.
Not sure why the behavior differs with and without a debugger attached though.
This is a follow up to my initial question and I would like to present my findings and ask for corrections, ideas and insights. My findings (or rather interpretations) come from people's answers to my previous question, reading MSDN .NET 3.5 documentation and debugging .NET 3.5 code. I hope this will be of value to someone who was wondering like me how to detect when an application terminates.
Events:
System.AppDomain.CurrentDomain.ProcessExit: raised when process exits, e.g. after the default AppDomain and everything else was unloaded [Total execution time is limited to just 3 seconds!]. For WPF, use System.Windows.Application.Exit instead. For Windows Forms, run code after Application.Run(...) in main method.
System.AppDomain.CurrentDomain.DomainUnload: raised when an AppDomain other than default AppDomain unloads, e.g. when running classes with unit testing frameworks (MbUnit with TestDriven.NET).
System.AppDomain.CurrentDomain.UnhandledException: (if handled in default AppDomain:) raised for any unhandled exception in any thread, no matter what AppDomain the thread started in. This means, this can be used as the catch-all for all unhandled exceptions.
System.Windows.Application.Exit: raised when WPF application (i.e. the default AppDomain) exits gracefully. Override System.Windows.Application.OnExit to take advantage of it.
Finalizers (destructors in C#): run when garbage collector frees unmanaged resources. [Total execution time is limited!].
Order of events:
WPF application: graceful exit
System.Windows.Application.Exit
System.AppDomain.CurrentDomain.ProcessExit
Finalizers
WPF application: unhandled exception
System.AppDomain.CurrentDomain.UnhandledException
MbUnit running inside TestDriven.NET: passed test (graceful exit)
System.AppDomain.CurrentDomain.DomainUnload
Finalizers
MbUnit running inside TestDriven.NET: failed test (unhandled exceptions are handled by MbUnit)
AppDomain.CurrentDomain.DomainUnload
Finalizers
Questions:
Are my interpretations/findings correct?
Do you know of more details that I have
left out? E.g. what is the total
execution time for finalizers?
Do you know of any other events /
ideas that I be aware of?
What events are there and what order do they get raised in other applications, e.g. Windows Forms, Web Service, ASP.NET web site, etc?
Prompted by ssg31415926's question/answer (this question is a bit reversed), there's also Application.SessionEnding which is called when the when the user logs off or shuts down. It is called before the Exit event.
When Dispatcher.BeginInvokeShutdown() is called, Application.Exit will not be called.
The default timeout for a finalizer's execution is 2 seconds.
You write:
System.AppDomain.CurrentDomain.UnhandledException: (if handled in default AppDomain:) raised for any unhandled exception in any thread, no matter what AppDomain the thread started in. This means, this can be used as the catch-all for all unhandled exceptions.
I do not think that this is correct. Try the following code:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AppDomainTestingUnhandledException
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
(sender, eventArgs) => Console.WriteLine("Something went wrong! " + args);
var ad = AppDomain.CreateDomain("Test");
var service =
(RunInAnotherDomain)
ad.CreateInstanceAndUnwrap(
typeof(RunInAnotherDomain).Assembly.FullName, typeof(RunInAnotherDomain).FullName);
try
{
service.Start();
}
catch (Exception e)
{
Console.WriteLine("Crash: " + e.Message);
}
finally
{
AppDomain.Unload(ad);
}
}
}
class RunInAnotherDomain : MarshalByRefObject
{
public void Start()
{
Task.Run(
() =>
{
Thread.Sleep(1000);
Console.WriteLine("Uh oh!");
throw new Exception("Oh no!");
});
while (true)
{
Console.WriteLine("Still running!");
Thread.Sleep(300);
}
}
}
}
As far as I can tell, the UnhandledException handler is never called, and the thread will just silently crash (or nag at you if you run it in the debugger).
Just add a new event on your main form:
private void frmMain_Load(object sender, EventArgs e)
{
Application.ApplicationExit += new EventHandler(this.WhenItStopsDoThis);
}
private void WhenItStopsDoThis(object sender, EventArgs e)
{
//Program ended. Do something here.
}
I'm wondering what the best way is to have a "if all else fails catch it".
I mean, you're handling as much exceptions as possible in your application,
but still there are bound to be bugs, so I need to have something that
catches all unhandled exceptions so I can collect information and store
them in a database or submit them to a web service.
Does the AppDomain.CurrentDomain.UnhandledException event capture everything?
Even if the application is multithreaded?
Side note: Windows Vista exposes native API functions that allow any application
to recover itself after a crash... can't think of the name now... but I'd rather not
use it, as many of our users are still using Windows XP.
I have just played with AppDomain's UnhandledException behavior,
(this is the last stage the unhandled exception is registered at)
Yes, after processing the event handlers your application will be terminated and the nasty "... program stopped working dialog" shown.
:)
You still can avoid that.
Check out:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
P.S. Do handle the unhandled for Application.ThreadException (WinForms) or DispatcherUnhandledException (WPF) at the higher level.
In ASP.NET, you use the Application_Error function in the Global.asax file.
In WinForms, you use the MyApplication_UnhandledException in the ApplicationEvents file
Both of these functions are called if an unhandled exception occurs in your code. You can log the exception and present a nice message to the user from these functions.
For Winform applications, in addition to AppDomain.CurrentDomain.UnhandledException I also use Application.ThreadException and Application.SetUnhandledExceptionMode (w/ UnhandledExceptionMode.CatchException). This combination seems to catch everything.
On the main thread, you have the following options:
Console or Service application: AppDomain.CurrentDomain.UnhandledException
WinForms application: Application.ThreadException
Web application: Global.asax's Application_Error
For other threads:
Secondary threads have no unhandled-exceptions; use SafeThread
Worker threads: (timer, threadpool) there is no safety net at all!
Bear in mind that these events do not handle exceptions, they merely report them to the application--often when it is far too late to do anything useful/sane about them
Logging exceptions is good, but monitoring applications is better ;-)
Caveat: I am the author of the SafeThread article.
For WinForms, don't forget to attach to the current Thread's unhandled exception event too (especially if you are using multi threading).
Some links on best practices here and here and here (probably the best exception handling article for .net)
There's also a cool thing called ELMAH that will log any ASP.NET errors that occur in a web application. I know you're asking about a Winform App solution, but I felt this could be beneficial to anyone needing this type of thing on a web app. We use it where I work and it's been very helpful in debugging (especially on production servers!)
Here's some features that it has (pulled right off the page):
Logging of nearly all unhandled exceptions.
A web page to remotely view the entire log of recoded exceptions.
A web page to remotely view the full details of any one logged exception.
In many cases, you can review the original yellow screen of death that
ASP.NET generated for a given
exception, even with customErrors mode
turned off.
An e-mail notification of each error at the time it occurs.
An RSS feed of the last 15 errors from the log.
A number of backing storage implementations for the log, including
in-memory, Microsoft SQL Server and
several contributed by the community.
You can monitor most exceptions in that handler even in multithreaded apps, but .NET (starting with 2.0) won't allow you to cancel unhandled exceptions unless you enable the 1.1 compatibility mode. When that happens the AppDomain will be shut down no matter what. The best you could do is launch the app in a different AppDomain so that you can handle this exception and create a new AppDomain to restart the app.
I am using the following approach, which works and reduces greatly the amount of code ( yet I am not sure if there is a better way or what the pitfalls of it might be.
Whenever you call:
I quess the quys giving minuses would be polite enough to clarify their actions ; )
try
{
CallTheCodeThatMightThrowException()
}
catch (Exception ex)
{
System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace ();
Utils.ErrorHandler.Trap ( ref objUser, st, ex );
} //eof catch
And here is the ErrorHandler code :
Just to make clear- : objUser - is the object modelling the appusers ( you might get info such as domain name , department , region etc. for logging purposes
ILog logger - is the logging object - e.g. the one performing the logging activities
StackTrace st - the StackTrace object giving you debugging info for your app
using System;
using log4net; //or another logging platform
namespace GenApp.Utils
{
public class ErrorHandler
{
public static void Trap ( Bo.User objUser, ILog logger, System.Diagnostics.StackTrace st, Exception ex )
{
if (ex is NullReferenceException)
{
//do stuff for this ex type
} //eof if
if (ex is System.InvalidOperationException)
{
//do stuff for this ex type
} //eof if
if (ex is System.IndexOutOfRangeException)
{
//do stuff for this ex type
} //eof if
if (ex is System.Data.SqlClient.SqlException)
{
//do stuff for this ex type
} //eof if
if (ex is System.FormatException)
{
//do stuff for this ex type
} //eof if
if (ex is Exception)
{
//do stuff for this ex type
} //eof catch
} //eof method
}//eof class
} //eof namesp
In a manged GUI app, by default, exceptions that originate in the GUI thread are handled by whatever is assigned to the Application.ThreadException.
Exceptions that originate in the other threads are handled by AppDomain.CurrentDomain.UnhandledException.
If you want your GUI thread exceptions to work just like your-non GUI ones, so that they get handled by AppDomain.CurrentDomain.UnhandledException, you can do this:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
An advantage to catching the GUI thread exceptions using ThreadException is that you can give the use the options of letting the app continue. To make sure no config files are overriding default behavior, you can call:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
You are still vulnerable to exceptions from badly behaved native dlls. If a native dll installs its own handler using Win32 SetUnhandledExceptionFilter, it is supposed to save the pointer to the previous filter and call it too. If it doesn't do that, your handler wont' get called.