How to gracefully terminate a process?
Asked Answered
C

6

46

I want to terminate a number of processes, but I want to give each process the chance to save its data, ask the user about saving a file and even ignore the close request.

So TerminateProcess is out of the question, because it kills the process instantly. Another way would be to use SendMessage/PostMessage to send a WM_CLOSE to the main window, unfortunately I don't know anything about the windows of the processes, I only have the process id, so FindWindow doesn't help either. Is there any other way to find the main windows of a process?

In other words: Is there any way to terminate any process gracefully just like the Windows 7 task manager did when you clicked on "End Task"? (and not "End Process")

Churn answered 13/1, 2010 at 9:53 Comment(4)
I assume that "Tasks" are top level (visible) windows. So, the WM_CLOSE will be sent (probably) on terminate task.Fouquiertinville
If you're not a software developer — just a Windows user — see the related Super User question on how to gracefully ask a running application to terminate.Dwanadwane
Note that, as of Windows 8.1, Task Manager's "End Task" button now forcibly terminates the chosen application and causes you to lose any unsaved work. You might want to edit your question in order to reflect this.Dwanadwane
The "End Task" button is/was about windows, not processes. The "End Process" button is/was about processes. Both are different things and under different tabs. One process can have zero to many windows.Tensiometer
T
31

EnumWindows enumerates all the top level windows in a process. GetWindowThreadProcessId gets the process and Id of each thread.

You now have enough information to gracefully close any GUI application.

You can send WM_CLOSE messages to any window you wish to close. Many windows handle WM_CLOSE to prompt the user to save documents.You can send a WM_QUIT message using PostThreadMessage to the discovered threads to cause the message loop to terminate.

User code is not allowed to call DestroyWindow from a different app or thread to the windows... if the app does not respond to WM_CLOSE or WM_QUIT requests you're back in TerminateProcess land.

This will not close console applications as the application process, and process that owns the window, are different.


Refer to T.s. Arun's answer below for the correct method for dealing with console applications.

Tillis answered 13/1, 2010 at 10:3 Comment(5)
When I have all the windows of the process, do I send a WM_CLOSE to each top-level window?Churn
Yes - TaskManager sends a WM_CLOSE message to the app. Actually I think it might send a WM_SYSCOMMAND, SC_CLOSE message.Tillis
Does this work to close the process without windows i.e. console ones?Clematis
What if process doesn't have any window? Let's say it is background driver monitoring task, having an icon in the tray. What if we develop that process ourselves, which means other than sending WM_CLOSE to a window do we have in Windows API? Is the only way to use Windows Sockets?Lempira
FarManager (which is a popular console app) apparently has a special window to handle such events: github.com/FarGroup/FarManager/blob/… Windows Sockets is a bad idea, use named events - learn.microsoft.com/en-us/windows/desktop/api/synchapi/… (with a non-null lpname). Commonly a GUID is used for such event names.Blackout
B
21

I'm not too sure about the win32 apis but you could shell execute the taskkill command line function.

taskkill /?
taskkill /pid 1230
taskkill /im notepad.exe

The /f switch would force the kill but not using it just sends the termination signal so the application closes gracefully.

Buckbuckaroo answered 13/1, 2010 at 10:3 Comment(6)
Unfortunately this is only available on Windows XP Professional or newer. (Not even XP home), but I need that functionality for Windows 2000 and XP Home, too. But I'd love to see the source code of that tool :)Churn
Starting a new process is the opposite of terminating one. Just running programs is not programming - this answer would fit Super User instead of Stack Overflow.Tensiometer
@Tensiometer this site is about helping programmers but it doesn't necessarily mean writing code for them, so there's nothing saying this answer doesn't belong here. You can argue whether it's the right approach, but executing shell commands is often a one-liner in programming languages and sometimes the easiest way to get something done. taskkill is predictable and well supported, you can think of it (and other built in she'll commands) as a universal functionBuckbuckaroo
"Executing shell commands" requires permission to do so, which can be denied, and taskkill.exe isn't even one - it's an executable/a separate file, which could be on a blacklist, too. Aiming at terminating a process by first creating a new process is not only ironic, but also more prone to fail than using any API - no matter how well expected its existence is. Super User has 40 Q's about this, including On Windows, how can I gracefully ask a running program to terminate?Tensiometer
Yet if you were scripting that's probably how you'd do it since Win32 APIs aren't necessarily available. Likewise, with some other scripting language it is the quick and simple option that will work for most cases. I take your point about it not being the best way, but there's nothing "ironic" about terminating a process by using another process that was purpose built for ending processes. Win32 APIs aren't without their faults either. For instance, a cursory google search suggests it's not possible to kill system processes with it.Buckbuckaroo
In any case, I'll leave the answer and it (or your comments) may be useful to someone in the future.Buckbuckaroo
V
14

See MSKB Q178893 How To Terminate an Application "Cleanly" in Win32. Basically send send WM_CLOSE to all windows of the target app to allow a grace shutdown, before force kill the app with TerminateProcess

Venesection answered 13/1, 2010 at 14:30 Comment(4)
+1. Overlaps a lot with Chris Becke's solution, plus describes handling corner cases with 16-bit apps. Nice.Eubank
You should also write some of the content here in case the page will be down/moved.Faucal
Link is currently down.Counterpressure
I believe the license on MSKB code is unclear, so you wouldn't be allowed to post it here. (because SO posts are licensed under CC BY-SA 4.0 currently) However here is an archive link of the content that works: web.archive.org/web/20150221153350/https://…Eury
D
6

To add to Chris Becke's answer about terminating gracefully terminating console process:

This event should be handled in the console application for graceful termination.

Dallon answered 25/4, 2018 at 10:33 Comment(1)
Here is an example of a practical implementation for this technique (C#): github.com/gapotchenko/Gapotchenko.FX/blob/…Chinkiang
L
3

Use the EndTask API function. It is the same function that is used by task manager.

BOOL EndTask(      
    HWND hWnd,
    BOOL fShutDown,
    BOOL fForce
);

http://msdn.microsoft.com/en-us/library/ms633492(VS.85).aspx

Lafontaine answered 23/1, 2010 at 16:40 Comment(3)
The very first line of text in that page says: [This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.]. Maybe the upvoters didn't click through?Yevette
@Yevette many api's have that hint but many problems cannot be resolved without using them. The same applies to "undocumented" ones. (i'm not saying this is one of such cases)Seriate
Task manager does not use EndTask. Instead it's a rather complicated code that try first to close process gracefully by sending messages, and later call TerminateProcess() as last resort.Instrumentality
C
-1

You can use taskkill /im your_program.exe to send a termination signal to the application. It will trigger a WM_CLOSE to windows message queue. You can use Either https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx or

https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessage

to process the message.

Please refer a similar answer Win32 API analog of sending/catching SIGTERM

Crossjack answered 12/4, 2019 at 4:15 Comment(1)
Starting a new process is the opposite of terminating one. Just running programs is not programming - this answer would fit Super User instead of Stack Overflow.Tensiometer

© 2022 - 2024 — McMap. All rights reserved.