Solved

How to emulate the WinNT Task Manager?

Posted on 1998-07-21
13
264 Views
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?
0
Comment
Question by:domenic
  • 5
  • 5
  • 2
  • +1
13 Comments
 
LVL 8

Expert Comment

by:trestan
ID: 1168231
Please take a look at the following KB article. I think it is what you need.
http://support.microsoft.com/support/kb/articles/q175/0/30.asp
0
 
LVL 1

Author Comment

by:domenic
ID: 1168232
KB Q175030 tells you how to retrieve pids. How do you get the process' state?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1168233
Use EnumWindows and SendMessageTimeout functions.
0
 
LVL 8

Expert Comment

by:trestan
ID: 1168234
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:
http://www.codeguru.com/misc/win32proc.shtml
Good luck.
0
 
LVL 1

Author Comment

by:domenic
ID: 1168235
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.
0
 
LVL 23

Expert Comment

by:chensu
ID: 1168236
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.
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 1

Author Comment

by:domenic
ID: 1168237
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.

Recommendations?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1168238
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.
0
 
LVL 1

Author Comment

by:domenic
ID: 1168239
Chensu,

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?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1168240
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.".
0
 
LVL 1

Expert Comment

by:payn
ID: 1168241
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...

0
 
LVL 1

Author Comment

by:domenic
ID: 1168242
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?
0
 
LVL 23

Accepted Solution

by:
chensu earned 150 total points
ID: 1168243
Grade this answer so that we can complete it.

Thank you.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now