We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now


How to emulate the WinNT Task Manager?

domenic asked
Medium Priority
Last Modified: 2012-05-04
I am writing a watchdog app which will monitor/stop/start other apps. I am able to retrieve pids for each app and CreateProcess if it has stopped running. I am able to TerminateProcess if need be. But I can not figure out how to communicate with the app in order to determine if the app is ' running' or 'not responding' (as seen with the Task Manager). I do not know if ::SendMessage() or PostMessage() is the way to go. I do have a process handle but I do not know how to get its corresponding Window handle( hWND) as needed by SendMessage() and PostMessage().  IPC? Too much work right now. Any suggestions?
Watch Question

Please take a look at the following KB article. I think it is what you need.


KB Q175030 tells you how to retrieve pids. How do you get the process' state?

Use EnumWindows and SendMessageTimeout functions.

To get process status, you need to use Performance Data Helper:
Platform,SDK and DDK Documentation -> Platform SDK -> Windows BaseServices -> General Library -> Performance Data Helper.
Or use The Registry Interface directely.
Fortunately, there is someone already made an example. It is easier to understand and modify to fit for your usage:
Good luck.


Trestan your link displayed a valid example of determining what pids are active out there using the Registry. I am using the PSAPI calls to get me the same information with less code. However, I am interested in determining a full proof method of knowing when a process/app is in a 'not responding' state. I think Chensu has given me a clue on how to get a window handle to the process and send it a health message. Maybe we can elaborate more on this method.

OK. Use EnumWindows to enumerate all the top-level windows and call GetWindowThreadProcessId to determine to which the process belongs. Call SendMessageTimeout with a time-out period, if it fails or time out, the window may be not responding.


EnumWindows. What does it really do?!! Here is what I have so far.
Let us go over my objective - Make sure that a certain process is actually running.

EnumProcesses - gets me all pids
OpenProcess, EnumProcessModules, GetModuleFileName tells me that my.exe = this_pid

// this_pid is confirmed with the Task Manager as truly being my.exe's pid.

Here's my code:

EnumWindows( (WNDENUMPROC)CheckForResponse,                                 (LPARAM) this_pid );
                         result=WaitForSingleObject(hProcess, 20000);
if( result == WAIT_TIMEOUT )
     ProcessStatus = _T("Not Responding");
else if( result == WAIT_OBJECT_0 )
     ProcessStatus = _T("Running");
else if( result == WAIT_FAILED )
     CString ErrStr;
     ErrStr.Format( "Error=%d", GetLastError );
    AfxMessageBox( ErrStr);
BOOL CALLBACK CheckForResponse( HWND hwnd, LPARAM lParam )
      DWORD dwID;
      DWORD result;
      char ProcTitle[MAX_PATH];
                     CString Str;
      dwID = 0;
      result = GetWindowThreadProcessId( hwnd, &dwID );

      if( dwID == (DWORD)lParam )
                          // Oddly enough I get three matches for this_pid
                          // I get a window called OleMainThreadWndName
                          // I get a window with no name
                         // and I get what I expect - my.exe

           ZeroMemory( ProcTitle, MAX_PATH );
           GetWindowText( hwnd, ProcTitle, MAX_PATH );
                           Str.Format( "%s", ProcTitle );

                         // because of these three matches I get the one I
                         // really want
                          if( Str.Find( "my.exe" )  != -1 )
                                //Send it any message??
                  PostMessage( hwnd, WM_TIMER, 0, 0 );
                                //No more enumerations
                 return FALSE;
      return TRUE;

The problems I encounter are:

1. Why are there 3 matches to the pid?
2. The process gets the WM_TIMER message but WaitForSIngleObject always times out, therefore I incorrectly label it "Not Responding"
3. What use is the return value of GetWindowThreadProcessID() ?

I have tried using WM_CLOSE and it is successful but I do not want to terminate my process unneccessarily.


1. I don't understand.
2. A process object's state is signaled only when the process terminates.
3. The return value is the identifier of the thread that created the window.



Let me re-iterate problem 1. GetWindowProcessId() returns 3 hwnds with the same pid. I used GetWindowText() to see what these windows are. As I stated before, I get a window "OleMainThreadWndName", "", and "My.exe". I am confused why there are other windows associated with the pid.

Re:2. A process object's state is signaled only when the process terminates.
Are you saying that WaitForSingleObject() returns successfully only when a process objects's state terminates? Should I then send a message back to the watchdog process? Or use the SendMessageTimeout()? I have used it but I am skeptical. If SendMessageTimeout() returns TRUE is it safe to assume that the process is responding?

1. It is possible because some processes/threads (especifially system threads) may create more than one top-level window.

2. >Are you saying that WaitForSingleObject() returns successfully only when a process objects's state terminates?
In your case WaitForSingleObject(hProcess, 20000), the function succeeds only when the process terminates (WAIT_OBJECT_0) or time out (WAIT_TIMEOUT).
>If SendMessageTimeout() returns TRUE is it safe to assume that the process is responding?
Yes. Because "The function calls the window procedure for the specified window and, if the specified window belongs to a different thread, does not return until the window procedure has processed the message or the specified time-out period has elapsed.".

To clarify what Chensu has said:

WaitForSingleObject(), when called on a process, waits for the process to terminate.

SendMessageTimeout() is an imperfect solution, but it's the best you can do using the general Win32 API (meaning that it's the best thing that will work with Win95). If you receive a TRUE before the timeout, the process is definitely responding (well, it's at least responding to some messages; I suppose if the app dispatches different messages to different threads and one or more of those threads are hung you might not find that out, but this is Windows, not BeOS, so I don't think you'll see a problem).

If problem is, if you receive FALSE, it doesn't necessarily mean the process isn't responding. If could just be doing something slow. Or blocking on user input (e.g. Outlook '97's "Please close Outlook by logging out" message). Of course the longer you wait, the more sure you can be that the process really is dead, but you can never be 100% sure (especially with apps like Outlook--my recommendation is just to kill Outlook whenever you see it :-) This is why Win95 itself is so bad at distinguishing dead processes.

As far as the WM_CLOSE solution, well, I suppose that has a use. If the message doesn't respond to WM_CLOSE it's presumed frozen, so you explicitly kill it. The problem is, if the app wasn't frozen, it'll be closed now. It's sort of like an old-fashioned witch trial--toss her in the water; if she floats she's guilty and we can kill her; if she drowns she was innocent...

There may be a better solution that's NT-specific (the NT task manager certainly seems to be better at detecting frozen apps that the 95 equivalent, although it seems to miss windowless zombie processes even more often), but I don't know what it is off the top of my head.

Probably the NT 6.0 task manager will be automatable...


Payn, thanks for the information. I just wanted to add that I am writing on a NT platform. For now I am using SendMessageTimeout() and thanks to Chensu it does perform satisfactory. In the future I will investigate IPC Messaging ( like Unix - good ol' days).

About Experts Exchange .....
When we  are satisfied with the expert's answer how do we complete it?
Unlock this solution and get a sample of our free trial.
(No credit card required)
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.