C# Perform one last action on application crash - c#

I'm not sure if there is a proper term for what I want to because any I've tried in google haven't bought anything up.
Basically, on an application crash I would like to perform a final action to clean up database record locking.
I would also like to catch this when debugging is stopped using the stop button, as I understand it using the stop button is very different to exiting your application by a normal process in your application.
Is there a normal way for achieving what I'm trying to do? The application is a C#, .NET 3.5 Windows Forms Application written in VS2008.
Cheers

You can't do anything within a process after it's killed.
Your only way to achieve what you want would be to have a second process that watched for the first one dying, and then did the cleanup on its behalf.
You have to worry about the second process crashing, or being killed, and so on. Not easy to make it work in all conceivable cases, but a lot better than nothing.

Check if any of the solution on Handling end process of a windows app helps you.

I don't think its possible to catch when the user stops the process via the debugger, however, you can override the OnUnhandledException event to catch when any exceptions are raised and not caught by your application.

The answer to your first requirement is to have (at it's most basic):
try
{
// Main application
}
catch // Though you might not want this
{
}
finally
{
// This code always executed even if application crashes.
}
However there are other considerations when dealing with Windows applications as RichardOD indicates in his comments here - http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx and here http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx
The answer to your second requirement is no you can't trap the application being stopped in the debugger (or at least there's not a way I've come across). It just kills the process.
For instance if you have stopped at a break point and then press stop the code doesn't carry on executing to termination - it just exits.
The same is true if the application stops due to some external factor like the power being turned off. In scenarios like this there's no way that the program can execute any code whether it's in a finally block or not!
However, I've just come across this question Visual Studio : executing clean up code when debugging stops which has an answer that states:
You can use the DTE (VisualStudio
Automation Model) to write a macro
that will be invoked when a stop debug
happens, below is a snippet of the
idea.
Private Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason, ByRef ExecutionAction As EnvDTE.dbgExecutionAction) Handles DebuggerEvents.OnEnterDesignMode
If (Reason = dbgEventReason.dbgEventReasonStopDebugging) Then
// DO YOUR CLEAN UP CODE HERE
End If
End Sub
So while you can't trap the stopping of the execution in your application you can do something about it in Visual Studio.
NOTE: Answer provided by Shay Erlichmen not me!

You could subscribe to the Application.ThreadException event when your program starts up, before you call Application.Run. This will give you a chance to do something if your application throws and exception. It will not do anything, however, for catching the debugger when you hit stop.
<SecurityPermission(SecurityAction.Demand, Flags:=SecurityPermissionFlag.ControlAppDomain)> _
Public Shared Sub Main()
AddHandler Application.ThreadException, AddressOf ErrorHandlerForm.Form1_UIThreadException
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
' Run the application.
Application.Run(New Form1())
End Sub
Private Shared Sub Form1_UIThreadException(ByVal sender As Object, ByVal t As ThreadExceptionEventArgs)
' Handle exception
End Sub
Your other option is to just surround your Application.Run in a Try...Catch block, which should give you similar results.

If you're targeting Windows Vista (or above) you might be interested in the RegisterApplicationRecoveryCallback API...
http://msdn.microsoft.com/en-us/library/aa373345.aspx
It doesn't address the debugging scenario, but it does allow you to do something when your app is about to crash.
You can p/invoke to this API from C# (I have done it), but bear in mind that when your callback is invoked your app is already in a very bad state, and you can make very few assumptions about the state of your memory. If you have any in-memory data that you want to use in this routine, I would put it in a static at a very general scope so that you have the best possible chance of it not having been "tidied up" when your callback routine runs.
There are some other interesting APIs, related to this one, that allow you automatically restart your app after a failure, etc.

A "normal way for achieving what you're trying" is to make sure your application never crashes.
You can also provide a standalone application which will let system administrator to release any file locks which might be left for whatever reason (power outage, ...). Such application could be used to fix this as well.

Related

Application shutting down without notice

I am currently managing a complicated application. It's written in C# and .Net 4.7.2.
Sometimes this program shuts down without notice. No error message even with a try/catch block and MessageBox.Show() in the Main method (I know it's probably not the best way but should work).
There are several threads running at different points, calling external DLLs and sometimes even drivers. So in order to log whether it's another thread that crashes the whole thing, I do this at the beginning :
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
Because I'm not sure which one is the correct one. In the methods, I log the Exception (after performing null checks) into a file (using File.AppendText and a timestamped based file).
Still nothing. The application keeps crashing after some random amount of time (between 2 and 6 hours) and I have no log information, no error message and I'm getting kind of lost here.
The app is running in Release mode and I cannot use Visual Studio to run the debugger into it (because that would make it easy). Maybe there's another way to run an external debugger ?
Can someone give me a hint on how to catch up for an exception that would cause an application to crash silently ?
Based on your explanations the only thing that brings to my mind is that you have some fire and forget threads in your application that throw exception sometimes but your application can't keep track of them to log or catch their exceptions.
Make sure all your tasks are awaited correctly and you don't have any async void method.
If you really need some fire and forget actions in your app, at least keep them alive with something like private Task fireAndForgetTaskAliver in your classes.
Another probability could be memory leak in your app that causes stack overflow exception.
The only way to catch an exception that is not caught anywhere in the code is indeed to look it the Windows Event Log, under Applications.
Thanks to Pavel Anikhouski for his comment.

Keep an Application Running even if an unhandled Exception occurs

What ?
I am developing a Console Application that needs to keep running 24/7 No Matter WhatIs there any way to stop a Multi-Threaded Application from getting blown up by some unhandled exception happening in "some thread somewhere" ?
Why ?
Please refrain from giving lessons like "you should manage all your exceptions", "this should never happen" etc. I have my reasons : We are in test deployment and we need to keep this running, log exceptions, and restart all threads again. If anything unplanned happens and causes an unhandled exception to be thrown, it needs to be detected and some method called to restart all threads(atomicity is impossible due due the tier design)
This being said, I am aware it might no be possible to restart an application from "within" if it has blown because of and UnhandledException (which I already implemented).
So far, I have used Quartz.net's FileScan Job and a Flag File to detect stuff like that and restart the application from outwards. But this sounds hacky to me. I would like to find something cleaner and less quick and dirty.
DownVoting / Sniping Warning : I KNOW this might NOT be possible "as is'". Please be creative/helpful rather than abruptly critic and think of this more as an "Open question"
If it is going to run 24/7 anyway, why not just write it as a Windows service and take advantage of the recovery options built right into windows?
This approach has the additional advantage of being able to survive a machine reboot, and it will log failures/restarts in the system event logs.
You need to attach an event handler to UnhandledException event on the Current AppDomain:
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler
Inside the handler, you will have to somehow save enough state (to a file, database, etc.) for the restarted application to pass along to the new threads. Then instantiate a new instance of your Console application with a call to System.Diagnostics.Process.Start("MyConsoleApp.exe").
Be very careful to introduce logic to avoid a continuous loop of crash/restart/crash/restart.
You can't keep a process running "no matter what". What if the process is killed?
You don't want to keep a process running "no matter what". What if the process state is corrupted in such a way that "bad things" happen if it keeps running?
Well I can think of a few drawbacks in the following solution, but it is good enough to me for the moment :
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
CS = new ConsoleServer();
CS.Run();
}
public static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception exception = (Exception)e.ExceptionObject;
Logger.Log("UNHANDLED EXCEPTION : " + e.ExceptionObject.ToString());
Process.Start(#"C:\xxxx\bin\x86\Release\MySelf.exe");
}
If your using .Net 2.0 and above, the answer is you can't.
In the .NET Framework versions 1.0 and 1.1, an unhandled exception
that occurs in a thread other than the main application thread is
caught by the runtime and therefore does not cause the application to
terminate. Thus, it is possible for the UnhandledException event to be
raised without the application terminating. Starting with the .NET
Framework version 2.0, this backstop for unhandled exceptions in child
threads was removed, because the cumulative effect of such silent
failures included performance degradation, corrupted data, and
lockups, all of which were difficult to debug. For more information,
including a list of cases in which the runtime does not terminate, see
Exceptions in Managed Threads.
Taken from here:
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
If you want your application to survive, then you will need very aggressive try/catch around your methods so nothing escapes.
I would advise using a windows service as mentioned by others. It's the same as a console application, but with an extra bit of service layer code on top. You could take your console app and covert it to a service application easily. Just need to override service.start/pause/stop methods.

Finally Block Not Running?

Ok this is kind of a weird issue and I am hoping someone can shed some light. I have the following code:
static void Main(string[] args)
{
try
{
Console.WriteLine("in try");
throw new EncoderFallbackException();
}
catch (Exception)
{
Console.WriteLine("in Catch");
throw new AbandonedMutexException();
}
finally
{
Console.WriteLine("in Finally");
Console.ReadLine();
}
}
NOW when I compile this to target 3.5(2.0 CLR) it will pop up a window saying "XXX has stopped working". If I now click on the Cancel button it will run the finally, AND if I wait until it is done looking and click on the Close Program button it will also run the finally.
Now what is interesting and confusing is IF I do the same thing compiled against 4.0 Clicking on the Cancel button will run the finally block and clicking on the Close Program button will not.
My question is: Why does the finally run on 2.0 and not on 4.0 when hitting the Close Program button? What are the repercussions of this?
EDIT: I am running this from a command prompt in release mode(built in release mode) on windows 7 32 bit. Error Message: First Result below is running on 3.5 hitting close after windows looks for issue, second is when I run it on 4.0 and do the same thing.
I am able to reproduce the behavior now (I didn't get the exact steps from your question when I was reading it the first time).
One difference I can observe is in the way that the .NET runtime handles the unhandled exception. The CLR 2.0 runs a helper called Microsoft .NET Error Reporting Shim (dw20.exe) whereas the CLR 4.0 starts Windows Error Reporting (WerFault.exe).
I assume that the two have different behavior with respect to terminating the crashing process. WerFault.exe obviously kills the .NET process immediately whereas the .NET Error Reporting Shim somehow closes the application so that the finally block still is executed.
Also have a look at the Event Viewer: WerFault logs an application error notifying that the crashed process was terminated:
Application: ConsoleApplication1.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Threading.AbandonedMutexException
Stack:
at Program.Main(System.String[])
dw20.exe however only logs an information item with event id 1001 to the Event Log and does not terminate the process.
Think about how awful that situation is: something unexpected has happened that no one ever wrote code to handle. Is the right thing to do in that situation to run even more code, that was probably also not built to handle this situation? Possibly not. Often the right thing to do here is to not attempt to run the finally blocks because doing so will make a bad situation even worse. You already know the process is going down; put it out of its misery immediately.
In a scenario where an unhandled exception is going to take down the process, anything can happen. It is implementation-defined what happens in this case: whether the error is reported to Windows error reporting, whether a debugger starts up, and so on. The CLR is perfectly within its rights to attempt to run finally blocks, and is also perfectly within its rights to fail fast. In this scenario all bets are off; different implementations can choose to do different things.
All my knowledge on this subject is taken from this article here: http://msdn.microsoft.com/en-us/magazine/cc793966.aspx - please note it is written for .NET 2.0 but I have a feeling it makes sense for what we were experiencing in this case (more than "because it decided to" anyways)
Quick "I dont have time to read that article" answer (although you should, it's a really good one):
The solution to the problem (if you absolutly HAVE to have your finally blocks run) would be to a) put in a global error handler or b) force .NET to always run finally blocks and do things the way it did (arguably the wrong way) in .NET 1.1 - Place the following in your app.config:
<legacyUnhandledExceptionPolicy enabled="1">
The reason for it:
When an exception is thrown in .NET it starts walking back through the stack looking for exception handlers and when it finds one it then does a second walk back through the stack running finally blocks before running the content of the catch. If it does not find a catch then this second walk never happens thus the finally blocks are never run here which is why a global exception handler will always run finally clauses as the CLR will run them when it finds the catch, NOT when it runs it (which I belive means even if you do a catch/throw your finally blocks will still get run).
The reason the app.config fix works is because for .NET 1.0 and 1.1 the CLR had a global catch in it which would swallow Exceptions before they went unmanaged which would, being a catch of course, trigger the finally blocks to run. Of course there is no way the framework can know enough about said Exception to handle it, take for example a stack overflow, so this is probably the wrong way of doing it.
The next bit is where it gets a bit sticky, and I am making assumptions based off of what the article says here.
If you are in .NET 2.0+ without the legacy exception handling on then your Exception would fall out into the Windows exception handling system (SEH) which seems pretty darn similar to the CLR one, in that it walks back through frames until it fails to find a catch and then calls a series of events called the Unhandled Exception Filter (UEF). This is an event you can subscribe to, but it can only have ONE thing subscribed to it at a time, so when something does subscribe Windows hands it the address of the callback that was there before, allowing you to set up a chain of UEF handlers - BUT THEY DON'T HAVE TO HONOR that address, they should call the address themselves, but if one breaks the chain, bap, you get no more error handling. I assume that this is what is happening when you cancel windows error reporting, it breaks the UEF chain which means that the application is shut down immediately and the finally blocks are not run, however if you let it run to the end and close it, it will call the next UEF in the chain. .NET will have registerd one which is what the AppDomain.UnhandledException is called from (thus even this event is not guaranteed) which I assume is also where you get your finally blocks called from - as I can't see how if you never transition back into the CLR a managed finally block can run (the article does not go into this bit.)
I believe this has something to do with changes to how the debugger is attached.
From the .NET Framework 4 Migration Issues document:
You are no longer notified when the debugger fails to start, or when there is no registered debugger that should be started.
What happens is that you choose to start the debugger, but you cancel it. I believe this falls under this category and the application just stops because of this.
Ran this in both release and debug, in both framework 3.5 and 4.0, I see "in Finally" in all instances, yes running it from command line, went as far as closing my vs sessions, maybe it's something on your machine or as Kobi pointed out, maybe platform related (I'm on Win7 x64)

Handling end process of a windows app

Is it possible to capture the task manager end process of a windows application within the same windows application itself? I am using a C# 2.0 win app and I would like to do some database processing (change a flag from 'Y' to 'N' in the DB) when an end process happens.
No, it is not possible to hook the operating system's decision to end a process. Note, this is not done by task manger, ending a process is the responsibility of the kernel.
You will need to do two things here:
Connect event handlers to the normal user interface messages that tell a application to exit. Use these events to persist data, free resources, and otherwise exit cleanly.
Handle exceptions as appropriate to catch errors and clean up and save data if possible.
Here are a three links to Raymond's blog explaining why you cannot do what you are asking.
Why can't you trap TerminateProcess?
Why do some process stay in Task Manager after they've been killed?
The arms race between programs and users
Also, I addressed a similar StackOverflow question here.
How about a slightly different approach:
Have your application update a date time field e.g. LastPollDate every so often while it is running, and have a separate field e.g. "AppTerminatedNormally" which you set to N, and change to Y if you get a form close event.
If the app is killed via Task Manager, the date will not be updated any more, and your AppTerminatedNormally will still be no.
This way you could run a query that finds all rows where LastPollDate is older than 10 minutes and AppTerminatedNormally is N, and you would have all the sessions that were abnormally terminated.
You're all gonna spit at this post, but here goes...
You're trying to solve the problem at the wrong level (i.e. running code in your app when the kernal is killing the app). The real problem is about ensuring that the database correctly reflect the presence (or absence) of it's client application/s.
To solve this, avoid allowing applications to be in an "incongruent state" between user interactions. In other words, don't start transactions that you can't commit quickly, don't write data to files that leaves the file in a half-written or unreadable state, and don't hold resources in external to your application an incongruent state outside of user interactions. Put differently, if your app isn't busy responding to an event handler, it should be ready to close immediately.
If you follow the above practise, you'll find very few scenarios where you need to "quickly clean up" before terminating. Outside of interactions where a user clicks "OK" or "Save", etc. a well written application should be able to survive immediate termination without any lasting damage or corruption of it's data stores.
If you absolutely have to set a flag in the database upon exit (which sounds typical of a pattern used to detect whether a user is logged in or not), then consider either of the following alternatives:
Periodically (perhaps once every 30 seconds) insert/update a timestamp-like field in the database, to indicate how recently an application was online. Other applications can inspect these timestamps to determine how recently another application was online... if the value is within the last 30 seconds, the other app is still opnline.
As Woodhenge rightly suggested, create a seperate process (ideally a service) to monitor the status of the main application. Windows services can be configured to automatically restart in the event of a failure of the service. This monitoring process will then issue timestamps to the database.
Notice that both of the above suggestions solve the real problem (detecting whether applications are accessing the database) without ever leaving the database in an "incongruent state" (the aforementioned flag is "Y" when the application is actualy dead and the flag should be "N").
If you're targeting Windows Vista (or above) you might be interested in the RegisterApplicationRecoveryCallback API...
http://msdn.microsoft.com/en-us/library/aa373345.aspx
It allows you to specify a callback routine in your app that will be invoked when the process is about to crash. N.B. it is only for crashes, and won't automatically be called if the process is killed deliberately.
You can p/invoke to this API from C# (I have done it), but bear in mind that when your callback is invoked your app is already in a very bad state, and you can make very few assumptions about the state of your memory. If you have any in-memory data that you want to use in this routine, I would put it in a static at a very general scope so that you have the best possible chance of it not having been "tidied up" when your callback routine runs.
There are some other interesting APIs, related to this one, that allow you automatically restart your app after a failure, etc.
What you can do is get the Process ID and monitor the process and you can use HasExited property to check whether the process has end or not. Below is a quick VB code (Excuse me I dont have VS now. This was written by me in another forum)
Public Class Form1
Dim p As ProcessStartInfo
Dim process As Process
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
p = New ProcessStartInfo("iexplore.exe")
process = process.Start(p)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
MsgBox(process.Id)
If process.HasExited Then
MsgBox("yes")
Else
MsgBox("no")
End If
End Sub
End Class
Above code starts Internetexplorer and the button checks whether the process has end or not. You can use a similar process to get all running process and use the processID.
I do not think this is possible to do from within the application. The purpose of End Task is to immediately stop the process. This does not allow any clean up code to execute.
Shoban pointed out another way to accomplish your goal. Another application or service would need to look for the main process. When the other process cannot find the main process, you could do the database processing at that point.

When should one use Environment.Exit to terminate a console application?

I'm maintaining a number of console applications at work and one thing I've been noticing in a number of them is that they call Environment.Exit(0).
A sample program would look like this:
public class Program
{
public static void Main(string[] args)
{
DoStuff();
Environment.Exit(0);
}
}
I don't understand what the intent of the original programmer was in doing this? In my mind even without the Environment.Exit statement the program should exit just fine. That said, for one of these programs, it's console window has been remaining even after it was supposed to have closed so I'm really not sure what's going on there....
Am I missing something here? Or is there a reason why Environment.Exit should be called in this instance?
The only reason for calling Exit() as the last line of the Main method is if there might be other foreground threads running. They would stay running if execution just fell off the end of Main. Even in this case, it would usually be a better idea either to put in some explicit graceful termination into the other threads - or make them background threads to start with.
If you ever want to return a different exit code from Main, the simpler way to achieve that is to declare it to return int.
In short, I don't think you need Environment.Exit() here, and it's worth asking your colleagues exactly why they're using it - chances are they won't be able to give you a good reason, and it's another bit of fluff you can cut out.
Basically, the statement Environment.Exit(0) tells the operating system that this is a "clean" exit. There are other numbers as well, each with a different meaning like, Environment.Exit(1).
However, one thing to note is that the "Main" has been declared as returning nothing "void", so the exit code will really not have a meaning to it.
Just in case you wanted to know more about the different exit codes, have a look here:
System Error Codes (0-499)
This is (compatibility) for command-line programs to indicate success or failure to an underlying shell, and is inherited from older C-style main loops where the prototype of the main function was
int main(void);
int main(int argc, char *argv[]);
The return value of 0 traditionally meant success, while non-zero meant failure or something else, depending on what the programmer decided.
References
Wikipedia for more information on the main function.
MSDN documentation on Environment.Exit()
In .NET Core, as of right now, one must use Environment.Exit to terminate their program on Mac. Purely returning from main doesn't stop the process and it keeps running until the user aborts it. Patterns like:
public class Program
{
public static void Main(string[] args)
{
Environment.Exit(TryRun(args));
}
}
are common in my work place because we want to ship for both Windows and Mac.
I'm currently using Environment.Exit() in a console application where I don't want to throw ugly exception text back to the console. Instead, I just notice the condition, write a user-friendly message to the screen about what happened and then call Environment.Exit().
Otherwise, you shouldn't need to call it from Main() in a basic console application.
In SSIS, when you have an Execute Process Task and you want to know if process is failure, this method is useful.
This is really used when other applications are waiting on the result of your console application. For example, SQL Server Reporting Services (SSRS) (tool) can launch a console application and waits to get back a success of failure response. The Environment.Exit(0) sends back a successful execution message.

Categories

Resources