tags:

views:

635

answers:

4

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 task manager does when you click on "End Task"? (and not "End Process")

+4  A: 

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. There is no real way to close console applications gracefully on Windows. They need to support some kind of graceful close mechanism.

Chris Becke
When I have all the windows of the process, do I send a `WM_CLOSE` to each top-level window?
DR
Exactly what I was about to say. +1.
j_random_hacker
Yes - TaskManager sends a `WM_CLOSE` message to the app. Actually I think it might send a `WM_SYSCOMMAND`, `SC_CLOSE` message.
Chris Becke
+1  A: 

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
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 :)
DR
Ah fair enough.
Andy E
+5  A: 

How To Terminate an Application "Cleanly" in Win32

Sheng Jiang 蒋晟
+1. Overlaps a lot with Chris Becke's solution, plus describes handling corner cases with 16-bit apps. Nice.
j_random_hacker
+2  A: 

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