To illustrate the use of the tool, lets have a look at an
example. In Figure 1, we have the output of the tlist tool
(coming with the Windows Resource Kit).
It shows a tree like structure of the running processes.
We see two command line processor instances (CMD.EXE;
PID 1087 and 1116) that was started by the Windows Explorer
(explorer.exe; 1220). The parent process that started the
Windows Explorer itself is no longer around, so climbing
the process hierarchy has to end here.
C:\Documents and Settings\userid> tlist.exe /t
System Process (0)
System (8)
SMSS.EXE (140)
CSRSS.EXE (164)
WINLOGON.EXE (184) NetDDE Agent
SERVICES.EXE (212)
...
explorer.exe (1220) Program Manager
CMD.EXE (1087) Command Prompt
CMD.EXE (1116) Command Prompt - tlist.exe /t
tlist.exe (1672)
C:\Documents and Settings\userid> _
|
|
Figure 1: Stripped down output of the tlist tool.
This output also shows a very practical problem. How to
programmatically differentiate between multiple instances
of the same program? How can for instance a batch file
find out which CMD.EXE is interpreting it? This is where
getpids comes into play. So lets run it in the same command
line window we ran tlist.exe before:
C:\Documents and Settings\userid> getpids.exe
1660 1116 1220
C:\Documents and Settings\userid> _
|
|
Figure 2: Output of the getpids tool.
As we can see, the getpids output represents the process
hierarchy by printing the chain of PID's as a blank seperated
list - starting with the process id of the getpids instance
itself. So in this example getpids was executing under PID
1660. It was run from the command line processor (CMD.EXE)
instance with the PID 1116 which itself was started by the
Windows Explorer (explorer.exe; PID 1220).
Given this simple output format, one can easily process it
from within a Windows batch file. The ZIP file (see the
download section) contains an example (sample.bat) for that
as well.
In contrast to a lot of Unix'es, Windows is not linearily
incrementing the PID as new processes are created. Instead
it picks a "random" PID which - on my system -
appears to be staying within the lower thousands range
(Solomon and Russinovich's excellent book unfortunately
doesn't provide details on this part of the process creation).
There is also a realistic chance of reusing a PID, so in the
example above it might happen, that for instance the PID of
the Window Explorer's parent process was reused again by
another process.
In such a case, false process hierarchy lists could be
created and in worst case there is even a change for
producing loops (e.g. if getpids would be the process to
reuse the mentioned process id). To avoid this from happening
getpids ensure consistency by comparing the process creation
timestamps and checking that the parent process was created
before the child process.
If you are nevertheless interested in the PID of the no
longer existing parent, then you can use the -x option
of getpids.
C:\Documents and Settings\userid> getpids.exe -x
1660 1116 1220 -1180
C:\Documents and Settings\userid> _
|
|
Figure 3: Output of the getpids tool.
Figure 3 shows an fictive output based on the earlier examples.
In addition to the earlier PID's, the list additionally contains
the PPID of the Windows Explorer. Indicating that this process
does no longer exist, we prefix it with a dash.