'End Task' in Task Manager always sets CloseReason.UserClosing
Asked Answered
T

2

8

I want to log if a customer tries to force close the application. I'm aware of having no chance to catch a process kill. But it should be possible through the main form closing event to get informed about the 'CloseReason.TaskManagerClosing' reason.

But any tests I did under Windows 8.1 I always got a CloseReason.UserClosing reason. But in this case (compared to a normals CloseReason.UserClosing) I've about 0.2s to run user code afterwards my program is killed!

Is this a new behavior in Windows 8.1?

Tirol answered 7/3, 2014 at 13:11 Comment(0)
P
10

Yes, I see this. And yes, this is a Windows change, previous versions of Task Manager sent the window the WM_CLOSE notification directly. I now see it issue the exact same command that's issued when you close the window with the Close button (WM_SYSCOMMAND, SC_CLOSE). Or press Alt+F4 or use the system menu. So Winforms can no longer tell the difference between the Task Manager and the user closing the window and you do get CloseReason.UserClosing.

What happens next is expected, if you don't respond to the close command quickly enough then Task Manager summarily assassinates your program with TerminateProcess().

Do keep in mind that trying to save data when the user aborts your program through Task Manager is a bad practice. Your user will normally use this if your program is malfunctioning, you can't really trust the data anymore and you risk writing garbage. This is now compounded by your saving code being aborted, high odds for a partially written file or dbase data that isn't usable anymore.

There is no simple workaround for this, the odds that Windows is going to be patched to restore old behavior are very close to zero. It is very important that you save your data in a transactional way so you don't destroy valuable data if the saving code is aborted. Use File.Replace() for file data, use a dbase transaction for dbase writes.

An imperfect way to detect this condition is by using the Form.Deactivate and Activate events. If you saw the Deactivate event and the FormClosing event fires then reasonable odds that another program is terminating yours.

But the normal way you deal with this is the common one, if the user ends the program without saving data then you display a dialog that asks whether to save data. Task Manager ensures that this doesn't go further than that.

Photodynamics answered 7/3, 2014 at 13:55 Comment(3)
Hans, Message.LParam tells something about this... but not reliable thoughHoppe
Thank you, I didn't intend to save data when the program is closing. I was looking for a reliable way to log when my application is terminated in an abnormal manner. Customer often tell us they haven't killed the process an I'm pretty sure they have...because in any other situation each step is logged in detail.Tirol
Then logging the De/Activate events is an excellent solution.Photodynamics
B
0

Another solution for determining when the Task Manager is closing the program is by checking if the main form, or any of its controls, has focus. When you close via the Task Manager, the application is not focused, whereas if you close via the close button or Alt+F4, the application does have focus. I used a simple if check:

private void MyForm_Closing(object sender, FormClosingEventArgs e)
{
    if (this.ContainsFocus)
    {
        // Put user close code here
    }
}
Breechloader answered 25/7, 2018 at 12:24 Comment(1)
If user does minimize a program and then close it through mouse context menu(right click on minimized application on task panel), the ContainsFocus remains false. So it's not really useful.Subminiaturize

© 2022 - 2024 — McMap. All rights reserved.