Executing code on application crash - c#

I have some clean up code that I would like to execute at the end of execution even if my C# application crashes (delete temp files, etc). Is that possible to do in C#?
Thanks!

It depends on what you mean by "crash".
If you want to deal with any unhandled exceptions that would otherwise bring down an application, you can attach an event handler to the AppDomain.UnhandledException event and then handle any errors in the event handler.
Additionally, in .Net 4.0 there is an AppDomain.FirstChanceException that is called before any catch blocks are executed when an exception occurs.
It is possible however that a real crash can occur (such as an exception being thrown from a finalizer) that causes a fatal application exit that cannot easily be handled, but in most cases the AppDomain.UnhandledException event will probably suffice.

If your application crashes then it isn't safe to try and execute cleanup code, you don't know what has been corrupted and until your application actually exits, files may be locked, etc.
So I would suggest that you put this cleanup code on application startup. Have your application look for temp files etc on startup before it gets around to creating it's normal temp files, if it finds them, then it can either delete them or attempt to fix/re-use them.
To facilitate this, you can have your application write a log of temp files that it creates and delete that log file when it shuts down successfully. That way when you find the log file on startup, you know that the last run was a crash and that you have to do your cleanup.
Of course, this gets more complicated if you allow several instances of your application to run at once, but the same goes for cleaning things up on crash as well.

There are several events that you can subscribe to in order to get notification of exceptions.
AppDomain.UnhandledException - Triggered by unhandled exceptions in the app domain.
Dispatcher.UnhandledException - Triggered by unhandled exceptions on a WPF dispather thread.
Application.ThreadException - Triggered by unhandled exceptions on background threads.
Also, as others have mentioned, a finally block around a single entry point will be hit for any exceptions on the main thread.
[I wouldn't recommend trying to recover your application from these handlers though. Particularly in the case of the AppDomain.UnhandledException event, your app is already on the way out, you should just let it shut down. Only use these handlers for doing last minute clean up or logging.]

If it is critical that your app cleans up, you can create a monitor app that would be what the user actually launches. It would launch your main app and then monitor its process handle. If your main app crashes, its process handle will signal and your monitor app can clean up and even restart the main app if you wish. I usually combine this with a named mutex that is used to signal back to the monitor app that the main app wishes to shut down, so that it won't restart it.

It depends on what you mean by "crash." If you mean an unhandled exception you can create a handler for Application.ThreadException. If the crash is caused outside of managed code, there's nothing you can do.

That's what try {} finally {} is for. Wrap all your code in your main method in it, that should do it.

Related

C# WinForms Tray application - not catching windows shutdown events

I'm writing a program that monitors state. It launches main window (LoginForm) to ask for user credentials, then hides the form. After that LoginForm inits NotifyIcon and all the remaining work is being done with LoginForm hidden. I've implemented all the clean-up work in FormClosing event of LoginForm. During normal exit process everything works perfectly.
The problem is that the program sits in tray all the time and I tend to forget to exit it before shutting down windows - program doesn't save the state on shutdown event.
I've read through many forums and docs, and from what I've read events FormClosing/FormClosed + SessionEnding/SessionEnded must fire anyway. But it looks like they just don't fire. Can't even cancel shutdown in SessionEnding (with stupid e.Cancel=true) - program disappears without reaching the place.
I've made myself a small debugging library to write out debug information into a file with instant flashing of cache. I've added debug messages to all the events. When I try to log off user in Windows (same as shutting down) for a test - I see no events being triggered usually, just the program vanishes. No exceptions I could catch, no events, etc. When exitting program manually or through "taskkill /IM " - I see all the expected debug printout. What's even more interesting - sometimes the program does reach closing events and does proper clean-up job during Windows shutdown.
Wasted a few days on this already. Overriden WndProc as suggested in MS article - program doesn't reach WndProc as well (to ensure it comes first before closing the form). Tried instead of FormClosing event to override OnClosing of LoginForm - no luck. Added UnhandledException handler, Microsoft.Win32.SessionEnding, Microsoft.Win32.SessionEnded, Form.FormClosing, Form.FormClosed event handlers - no luck.
I suspect this is either a problem of hidden forms or that some kind of exception is happening during shutdown only (resources disposed?). How can I find why that's happening? Is there some simple way to simulate Windows shutdown for single application to make debugging in VS possible? I've tried RMTool - for some reason it fails to simulate shutdown and program just ignores it.
Update: Program uses System.Timers.Timer to regularly poll server for any changes.
I've done some research into this, basically, after Windows XP they altered the way that shutdowns were handled.
You cannot block or capture the shutdown event reliably using the form_closing events etc.
You must use a new API to do so. There is a complete example here: http://bartdesmet.net/blogs/bart/archive/2006/10/25/Windows-Vista-2D00-ShutdownBlockReasonCreate-in-C_2300_.aspx
You should be able to call the function to block shutting down (display a message such as 'saving changes...') and then save and exit your application in the background. Once your program quits, it should allow windows to continue shutting down.
I think windows is simply configured to automatically shutdown all applications regardless and hence the application has no chance to catch SessionEnding events and so on : have a look at http://www.addictivetips.com/windows-tips/disable-automatic-termination-of-applications-during-shutdown-in-windows-7/ or check your configuration at Computer Configurations > Administrative Templates > System > Shutdown Options.

.NET CF application on Windows Mobile freezing with no details in the global exception handler

I am developing a .net cf application for a windows mobile device - the Motorola ES400.
The application maintains a log file which logs all handled exceptions and the unhandled global exception which was registered in global scope of the application in the Main method.
For some reason, while I was running the application on the phone, the application just froze - which means that I was not able to click on any buttons on the application or perform any other actions with the stylus. The application was totally unresponsive. When I went back to the phone Windows Mobile OS Start menu->Task Manager and tried to close the application, I could not. The task manager would not close the application. When I checked the logs, I could not see any unhandled exception logged through the registeres unhandled global exception routine.
I don't understand what might be the problem here.
Does anyone have any idea on what might have happened based on your experience with .NET CF? Anywhere I could start looking or analyzing?
Thanks in advance for any help.
Subbu
There can be many reasons. In my experience, I suppose there is some infinite looping or call to some locked resource is happening. In such scenarios, try using CLR Profiler for .NET CF. CLR Profiler can show you what is going wrong and where.
You can get it from here: http://www.microsoft.com/en-us/download/details.aspx?id=13442
And about how to use it, there is series of blog posts, visit: http://blogs.msdn.com/b/stevenpr/archive/2008/05/08/the-clr-profiler-for-the-net-compact-framework-series-index.aspx
I hope it helps.
If you get a hard fault (OS-level error like memeory access violation) then I've seen the system freeze while the Dr Watson logs are getting created.
On the ES400 I don't recall if there is a control panel applet to confugure the error reporting feature or not, but check there.
If it was creating such a log, bu default I think it goes in a subfolder under \windows. But the whole process if configurable via the registry so you might want to look there.
See here for the topic in general:
http://msdn.microsoft.com/en-us/library/ee481217(v=winembedded.60).aspx
And here specifically for the registry settings:
http://msdn.microsoft.com/en-us/library/ee480226(v=winembedded.60).aspx
I had some problems similar to this a while ago. I was was using a barcode scanner driver that created a separate thread and looped until a barcode was scanned. When I tried to exit the application it would wait for the thread to stop, causing the application to freeze until a barcode was scanned. Task manager could not end the application either.
I believe if you have a foreground thread (Thread.IsBackground = false) this will prevent the process from terminating until it has ended - http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx
Therefore your problem may be from a secondary thread that you have started up. If you are waiting for a thread, through a lock or something like that, and that thread is in an infinite loop, then this could be the cause of your problem. My most common cause for an accedental infinite loop is having a property getter referencing the property instead of the backing variable.
I hope this is of some help.
If you simply want to catch and log this error, then put a try...catch around your code in the main function of your program.
In C#, this would be simply editing Program.cs from something like this:
static void Main() {
Application.Run(new Form1());
}
To something like this:
private static Form1 m_form;
static void Main() {
try {
m_form = new Form1();
Application.Run(m_form);
} catch (Exception err) {
// log error
if ((m_form != null) && !m_form.IsDisposed) {
// you might want to save data on your form before it goes Bye-Bye.
}
}
}

Program works on dev machine, but won't start on test machine

I've been writing this program for a while now, and I'm finally ready to start testing it. It works 100% on my dev machine, but I wanted to try it on a machine it's never run on. So, I get my program over to a test computer. When I double-click the exe, nothing happened. I opened up task manager, and tried again. I saw the process start, but after about 5 seconds, it disappeared. No errors, no exceptions, no nothing. How would I go about trying to figure out what is going wrong? I'm still fairly new, and I've never had this happen. Thanks for any and all help!
EDIT
Sorry for not mentioning before. This is a winforms application.
EDIT 2
So, turned out what was going on is that I was trying to a dll meant for 64-bit OS into a 32-bit OS. In Windows XP, this threw a BadImageFormatException. However, in Windows 7, as I stated, it threw no exception at all.
This is a pickle, no doubt about it. I've had to debug this type of thing before.
The first bit of useful information is that no exception is being thrown out. This tells me that somewhere in your actual code is the key to solving the problem. You are either trapping an exception and closing silently, or your code is hitting what it considers to be a "normal" exit condition and is closing in what it would consider the normal way.
To figure out where and why it's exiting, I would add debug logging at key points in your application, and attach a listener to the Debug/Trace listener collection that writes out to a file. "Key points" are places where the application is supposed to exit (or the main form of the window is supposed to close), and within any "catch" block or error event handler. Run this new version on the test computer and see what it gives you. That should tell you the basic flow of the program behind the scenes, and through what mechanism it's shutting down.
If you're running a console application, it is possible that it runs and then closes itself.
Trying opening a command prompt, and then executing the application from there.
If your program has output, then you would see it in that command window.
Have you checked the application event log?
Do you have the necessary version(s) of .Net installed?
Perhaps you should put more exception handling with calls to MessageBox.Show("I failed here") through out your application.

Running a cleanup after a program crashes

I'm currently writing quite a simple app, but it makes a change to the OS which gets changed back when the program is closed.
The worry of course, is if the program crashes. I can do everything in my power to prevent it from crashing, or handling things if it does crash - but I can't stop someone from force closing the process (unless I can?)
Is there a way to catch that event and run just a very quick cleanup before the process exits?
I don't think there is anything you can do if your process gets killed - one approach would be to have your app spawn a helper process that is just there for this case. When your app terminates that process can detect that and "fix" the OS setting as desired before it shuts down itself - obviously this only would work if that other process doesn't get killed first.
You can hook UnhandledException. You can't stop the application terminating, but you can log or do some clean up. This allows you to handle the case of application crashes.
It terms of someone actually just killing the process there's nothing you can do about that.
Program defensively.
Write the original settings to a file. Delete the file when closing. When starting, check whether the file is there - if it is, your process was killed and you know what to return the settings to.
Programming 201 - the basics of transactions, applied to system settings wit hthe program runtime as transaction boundary.
If you don't mind a little interop to C or C++ code, and if you're running on Windows Vista or newer, you could make use of the Application Recovery and Restart APIs. These APIs tell Windows to intercept your process when something catastrophic happens, so that you can perhaps call a little cleanup code before Windows kills the process completely.
See http://msdn.microsoft.com/en-us/library/cc948909.aspx.

C# application terminates unexpectedly

We run a C# console application that starts multiple threads to do work. The main function looks something like this:
try
{
DoWork();
}
catch (Exception err)
{
Logging.Log("Exception " + err.ToString());
}
Logging.Log("Finished");
The DoWork() function reads new jobs from a database, and spawns threads to process one work item each. Since last week, the application has started disappearing mysteriously. It disappears from the processes list and there is no entry in the event logs. The log file shows work up to a certain point: it does not log an exception, or the "Finished" line.
Any clue(s) on how a C# application can vanish like that?
EDIT: Threads are created like:
new Thread(SomeObj.StartFunc).Start();
Some of the disappearances occur when no threads are running.
P.S. We installed DebugDiag with a rule to create a crash dump whenever our program crashed. It did not create any dump files when the process disappeared.
You need to have a similar catch block at the top level of the function that every thread works. If there is an uncaught exception on a thread it will kill the application, and the catch block on the main thread is not going to help.
What's the identity that you're using to run the console application?
Also, you might want to use SetConsoleCtrlHandler to capture the console events. Look at this blog post for more details. We had a similar issue when the console application was run under a service account, and it would occasionally get terminated. I'm not sure if this is what you're running into. Let me know I can post some code.
UPDATE: It looks like your scenario resembles what we had experienced. In your console event handler, you need to check for the LogOff event and return true. Look at this KB article.
public static void inputHandler(ConsoleCtrl.ConsoleEvent consoleEvent)
{
if (ConsoleEvent == ConsoleCtrl.ConsoleEvent.CtrlLogOff)
return true;
return false;
}
It's possible that one of the threads that the DoWork method is spawning is throwing an exception. The default behavior in this case is for the process to terminate. You can stop this from happening by using the AppDomain.UnhandledException event to override the default behavior.
A console program quits when the main function exits. Since DoWork just spawns a few threads it's returning control to main right away, and since Main has nothing else to do it exits and the program ends. At this time the threads spawned by DoWork are also killed.
That it worked before means either there was something in DoWork() to wait on those threads that now returns right away (is broken) or that part still works but a thread that used to take a long time to return now aborts and returns right away.
It could perhaps be the Logging.Log function that throws your exception.
I have managed to make programs disappear without a trace in a similar fashion to you (no exception traces and no termination log messages) in the past. Almost all the time it was related to killing the stack (the name of this website always reminds me).
It is possible that you are suddenly trying to process far more data than usual, or using re-entrant routines, or being 'clever' with pointers.
DISCLAIMER: My experience was with a Win32 C++ application, not C#.
It could be a memory leak. If your application takes too much memory, Windows will kill it. You can check how much memory you are using: if it grows over time, you may have a memory leak.
Another possibility is that somewhere, you have code calling Environment.Exit(). Try a full text search through your code to double-check. You never know!
Be careful; there are some exceptions that cannot be caught: OutOfMemoryException and StackOverflowException.
Therefore your program will die terribly, but silently.

Categories

Resources