Monitoring open programs with Win32 Monitoring open programs with Win32 windows windows

Monitoring open programs with Win32


On windows, you can use PSAPI (The Process Status API) to know when processes are started and terminate. The EnumProcesses function can give you this information.

A more reliable method to determine that a process terminated (since process ids can be reused) is to wait on its process handle (you will need the SYNCHRONIZE access right) which you can obtain using OpenProcess and the process' id obtained from EnumProcesses.

To terminate a process, there is always TerminateProcess. To call TerminateProcess, you will need a handle to the process with the PROCESS_TERMINATE access right. All of this assumes that you have the privileges needed to perform these actions on the process to be terminated.


One thing to be aware of is that processes and programs - or at least what the user regards as a program - are not necessarily the same thing.

If you use the PSAPI to get a list of all the processes running, you'll see a lot of background process that don't correspond to open windows at all. There's also cases where a single process can have multiple top-level windows open. So while you have simple cases like notepad where once notepad.exe process corresponds to one Notepad window, you also have cases like:

  • Word, where one word process handles all the word documents currently open (one process, many windows)
  • Explorer, where a single exploere.exe process handles all the open explorer windows, and also things like control panel windows and the task bar.
  • Chrome (and other browsers), where each tab gets its own process (many processes, one window!)

Using TerminateProcess is perhaps not the best way to close an app: it's not directly equivalent to clicking the close button. It forcibly terminates the entire process there and then, without giving it any chance to clean up. If you do this on Word, when it restarts, it will go into 'recovery mode', and act as though it hadn't shut down cleanly the last time. It's best left as a last resort if a process has stopped responding. Also, if you TerminateProcess on a process like Word or Explorer, you'll end up closing all windows owned by that process, not just one specific one.

Given all of this, if you want to essentially write some sort of program manager, you might be better off taking a window-centric approach rather than a process centric one. Instead of monitoring running processes, monitor top-level application windows.

There are several ways to listen for changes to windows; SetWinEventHook with EVENT_CREATE/DESTROY is one way to listen for HWNDs being created or destroyed (you'll need to do filtering here, since it will tell you about all HWNDs - and more! - but you only care about top-level ones, and only app ones at that). SetWindowsHookEx may have other options that could work here (WH_CBT). You can also use EnumWindows to list the windows currently present (again, you'll need to filter out owned dialogs and tooltips, currently invisible HWNDs, etc).

Given a HWND, you can get process information if needed by using GetWindowThreadProcessId.

To close a window, sending WM_SYSCOMMAND/SC_CLOSE is the best thing to try first: this is closer to clicking the close button, and it gives the app a chance to clean up. Note that some apps will display a "are you sure you wish to close?" dialog if you haven't saved recently - again, it's consistent with clicking the close button with the mouse.


The most well-known way of doing this on Windows is to use the Process Status API. You can use this API to enumerate processes However, this API is annoying in that it doesn't guarantee you get the full list or processes.

A better way to enumerate processes is using the Tool Help Library, which includes a way to take a complete snapshot of all processes in the system at any given time.