Click here to Skip to main content
15,665,480 members
Articles / Programming Languages / C++
Posted 10 Jun 2002


18 bookmarked

Process Enumeration in Windows 2000

Rate me:
Please Sign up or sign in to vote.
4.60/5 (10 votes)
10 Jun 20024 min read
Explains how to use the ToolHelp API to enumerate processes under Windows 2000/XP


The advent of NT 5.0 has not only given a new face and improved technology to Windows NT 4.0 users, but has significant improvements for software developers as well, like introduction of COM+, expansion of the Win32 API set, just to name a few.

Under the expansion of the Win32 API, NT 5.0 now supports a new (for Windows NT) set of APIs which help enumerate, amongst other things, the processes and threads in the system. This API set was already present in Windows 95/98, but wasn't there in Windows NT 4.0, where this enumeration required interaction with the system registry.

This article intends to illustrate the enumeration of the processes and threads under a NT 5.0 system using this new set of APIs, which constitute the 32bit TOOLHELP API set (the prototypes are declared in TLHELP32.H). With introduction behind us, lets start enumerating.

The Snapshot

Whenever we use the TOOLHELP API to enumerate the system processes and threads, we have to create, what is called a ToolHelp Snapshot. This snapshot gets the details regarding the processes and threads, amongst other things, at a given point of time (which is the time the snapshot is created). To create the snapshot, we use the CreateToolhelp32Snapshot API whose syntax is:
HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags, 
DWORD th32ProcessID 
dwFlags tells the API whose snapshot do we wish to take. Passing the constant TH32CS_SNAPPROCESS takes a snapshot of all the active processes, while TH32CS_SNAPTHREAD does the same for the threads in the system. th32ProcessID is the ID of the process in whose context we intend to take the snapshot. We usually specify 0(zero) when taking snapshots of processes and threads, which aren't specific to a particular process. On the other hand, if we intend to enumerate a process specific entity, say the heap list, then we specify the ID of the process whose heap list we wish to enumerate.

If the snapshot is successfully created, the API returns a HANDLE to the snapshot. Otherwise, -1 is returned.

Onto Enumeration

Once we have the handle to the snapshot of the processes or threads or both (by ORing TH32CS_SNAPPROCESS and TH32CS_SNAPTHREAD and creating a snapshot), we proceed to enumerate the processes or threads.

TOOLHELP API exports two functions for enumerating Processes: Process32First and Process32Next. Process32First has the following prototype:

BOOL WINAPI Process32First(
HANDLE hSnapshot,

and Process32Next has an almost identical one:

BOOL WINAPI Process32Next(
HANDLE hSnapshot,

Both the APIs take the handle to a Process Snapshot and a pointer to a structure which shall contain the information regarding the enumerated process. This structure has the following structure:

typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage; 
DWORD th32ProcessID;
DWORD th32DefaultHeapID;
DWORD th32ModuleID; 
DWORD cntThreads; 
DWORD th32ParentProcessID; 
LONG pcPriClassBase; 
DWORD dwFlags; 
char szExeFile[MAX_PATH]; 


As you can see, LPPROCESSENTRY32 is basically a pointer to PROCESSENTRY32. The various fields of the structure are briefly documented below :

  1. dwSize: contains the size of the structure and must be initialized before passing the pointer to the structure to the API
  2. cntUsage: tells how many processes are using this process. One process may "use" another process, say for example, by opening that process. This is returned after enumeration.
  3. th32ProcessID: contains the ID of the process. This is returned after enumeration.
  4. th32DefaultHeapID: contains the ID of the default heap of the process. This is returned after enumeration.
  5. th32ModuleID: contains the ID of the module associated with the process. This is returned after enumeration.
  6. cntThreads: contains the number of threads belonging to this process. This is returned after enumeration.
  7. th32ParentProcessID: contains the process ID of the process which is parent to this process. This is returned after enumeration.
  8. pcPriClassBase: contains the base priority class of the process. This is returned after enumeration.
  9. dwFlags: officially, its documented as reserved!!!
  10. szExeFile: returns the path to the executable from which this process was created.

To start enumeration, we first call Process32First with the snapshot of the processes and a pointer to PROCESSENTRY32 structure (after filling its dwSize field). The API returns TRUE upon a successful enumeration and FALSE otherwise. Assuming a TRUE response, the PROCESSENTRY32 structure is filled with all the details regarding the process enumerated.

To continue the enumeration, we continue to call Process32Next with the snapshot of the processes and a pointer to PROCESSENTRY32 structure (after filling its dwSize field). Assuming a TRUE response, the PROCESSENTRY32 structure is filled with all the details regarding the process enumerated. Continue to do this repeatedly until the API returns FALSE.

Once the enumeration is complete, DON'T FORGET TO CLOSE THE HANDLE TO THE SNAPSHOT. Below I present the pseudo code to enumerate the process list under NT 5.0. Here it is:

#include <tlhelp32.h>
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_PROCESS,0);
if (hSnapshot==-1)
// error: unable to create snapshot


// fill up its size

BOOL retval=Process32First(hSnapshot,&pe);
printf("Process ID : %08X\n",pe.th32ProcessID);

// close snapshot handle

// viola.. we are done


So, that's it! The same code now can be used to enumerate processes under Windows 95/98 without any change!! Isn't that a relief... a more portable code. And with quite reduced complexity as compared to how it was done under NT 4.0!


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Written By
Web Developer
United States United States
I hold Early Acheiver in MCSE 2000, MCSE NT 4.0, MCP+I, and actively involved in programming using C/C++, .NET framework, C#, Win32 API, VB, ASP and MFC.

I also have various publications to my credit at MSDN Online Peer Journal, Windows Developer Journal (, Developer 2.0 (, and PC Quest (

Comments and Discussions

GeneralToolhelp Pin
Anonymous4-Jun-05 4:23
Anonymous4-Jun-05 4:23 
GeneralAccess Denied Pin
luc@vasco30-Sep-04 22:23
luc@vasco30-Sep-04 22:23 
QuestionHow do I get Process ID from a Thread ID Pin
mpvbrao18-Aug-04 2:05
mpvbrao18-Aug-04 2:05 
GeneralExe name limtation to 15 characters Pin
Yves Berquin5-Nov-03 22:02
sussYves Berquin5-Nov-03 22:02 
GeneralWell written, Gaurav Pin
Nish Nishant5-Oct-03 21:10
sitebuilderNish Nishant5-Oct-03 21:10 
Questionhow to get process owner? Pin
at4r17-Jun-03 1:15
at4r17-Jun-03 1:15 
AnswerRe: how to get process owner? Pin
Anonymous9-Jan-05 7:42
Anonymous9-Jan-05 7:42 
AnswerRe: how to get process owner? Pin
Anonymous8-Feb-05 17:05
Anonymous8-Feb-05 17:05 
GeneralRe: how to get process owner? Pin
matghaleb18-Feb-05 6:31
matghaleb18-Feb-05 6:31 
GeneralNot bad :) Pin
Philip Patrick11-Jun-02 11:04
professionalPhilip Patrick11-Jun-02 11:04 
GeneralRe: Not bad :) Pin
Irfan Dawood7-Sep-02 10:06
Irfan Dawood7-Sep-02 10:06 
GeneralRe: Not bad :) Pin
Yves Berquin5-Nov-03 21:59
sussYves Berquin5-Nov-03 21:59 
GeneralRe: Not bad :) Pin
Rogier29-Sep-04 7:41
Rogier29-Sep-04 7:41 
GeneralRe: Not bad :) Pin
kkez1-Feb-05 21:57
kkez1-Feb-05 21:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.