Handling end process of a windows app
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").