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")

Daniel Rikowski
  • 71,375
  • 57
  • 251
  • 329
  • I assume that "Tasks" are top level (visible) windows. So, the `WM_CLOSE` will be sent (probably) on terminate task. – Nick Dandoulakis Jan 13 '10 at 10:45
  • 1
    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](http://superuser.com/questions/959364/on-windows-how-can-i-gracefully-ask-a-process-to-terminate). – unforgettableidSupportsMonica Aug 19 '15 at 02:33
  • 1
    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. – unforgettableidSupportsMonica Aug 20 '15 at 12:44
  • 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. – AmigoJack Jun 11 '23 at 13:30

6 Answers6

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.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • When I have all the windows of the process, do I send a `WM_CLOSE` to each top-level window? – Daniel Rikowski Jan 13 '10 at 10:08
  • 2
    Yes - TaskManager sends a `WM_CLOSE` message to the app. Actually I think it might send a `WM_SYSCOMMAND`, `SC_CLOSE` message. – Chris Becke Jan 13 '10 at 13:13
  • 6
    Does this work to close the process without windows i.e. console ones? – rpattabi Feb 06 '12 at 14:10
  • 4
    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? – blackbada_cpp Mar 29 '16 at 08:54
  • FarManager (which is a popular console app) apparently has a special window to handle such events: https://github.com/FarGroup/FarManager/blob/0871bcdcbb7ca8dcbb6155edfbd5a5d426e5cccd/far/wm_listener.cpp#L53 Windows Sockets is a bad idea, use named events - https://learn.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-createeventw (with a non-null lpname). Commonly a GUID is used for such event names. – nponeccop Jun 29 '18 at 15:30
20

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.

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • 5
    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 :) – Daniel Rikowski Jan 13 '10 at 10:09
  • Starting a new process is the opposite of terminating one. Just running programs is not _programming_ - this answer would fit [Super User](https://superuser.com) instead of Stack Overflow. – AmigoJack Jun 11 '23 at 13:27
  • 1
    @AmigoJack 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 function – Andy E Jun 12 '23 at 22:55
  • "_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](https://superuser.com/questions/tagged/kill+windows), including [On Windows, how can I gracefully ask a running program to terminate?](https://superuser.com/q/959364/650342) – AmigoJack Jun 13 '23 at 07:25
  • 1
    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. – Andy E Jun 14 '23 at 18:32
  • In any case, I'll leave the answer and it (or your comments) may be useful to someone in the future. – Andy E Jun 14 '23 at 18:32
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

Sheng Jiang 蒋晟
  • 15,125
  • 2
  • 28
  • 46
  • +1. Overlaps a lot with Chris Becke's solution, plus describes handling corner cases with 16-bit apps. Nice. – j_random_hacker Jan 15 '10 at 02:57
  • 12
    You should also write some of the content here in case the page will be down/moved. – MasterMastic Apr 02 '13 at 14:58
  • 3
    Link is currently down. – owacoder Jan 22 '20 at 19:51
  • 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: https://web.archive.org/web/20150221153350/https://support.microsoft.com/kb/178893 – WebFreak001 May 05 '21 at 06:22
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.

AmigoJack
  • 5,234
  • 1
  • 15
  • 31
T.s. Arun
  • 317
  • 5
  • 17
  • 1
    Here is an example of a practical implementation for this technique (C#): https://github.com/gapotchenko/Gapotchenko.FX/blob/1accd5c03a310a925939ee55a9bd3055dadb4baa/Source/Gapotchenko.FX.Diagnostics.Process/ProcessExtensions.End.cs#L247-L328 – ogggre Mar 29 '19 at 05:34
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

Jason
  • 2,341
  • 17
  • 14
  • 11
    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? – Jon Jun 26 '11 at 22:59
  • 4
    @Jon 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) – Mauro H. Leggieri Oct 17 '14 at 12:02
  • 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. – tigrou May 05 '22 at 20:06
-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

amilamad
  • 470
  • 6
  • 9
  • Starting a new process is the opposite of terminating one. Just running programs is not _programming_ - this answer would fit [Super User](https://superuser.com) instead of Stack Overflow. – AmigoJack Jun 11 '23 at 13:17