getpids (V1.00)

Abstract

The getpids program is a small tool released under the GNU General Public License. It allows a calling Windows process (or batch file) to identify its process id (PID) or parent process id (PPID). The tool does so by reading its own process id and then using it to walk up the process hierarchy and gathering the process id's of the parent processes. The collected PID's are finally printed to STDOUT in an easy to parse format.

Download

The getpids executable as well as the sources are bundled in this ZIP file:

getpids-1.00.zip

Usage

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.

Details

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.

Feedback

In case you have comments, added functionality or found a bug, please feel free to contact me.