A couple of different ways to get EXE name from PID in Windows

I’ll preface this post with the fact that it will be fairly technical. I have been trying to write a Windows program which can get the EXE path of a specified process ID (PID). I found a couple different ways, so thought I would go through them here.

This Rhino is curious to find EXE paths of applications

So, while going through this process, I found 2 different ways of doing this, both from the Internet and combing through MSDN documentation. If you just want to get the full EXE path of a certain PID, turns out it is very simple. If you want to get a full PROCESSENTRY32 structure however, it’s a little more challenging.

First, the easier solution of just getting the full EXE path. Turns out there is a lovely system call called QueryFullProcessImageNameย that does exactly what I wanted. (Of course, I only found this after hours of searching and doing the other way, but that is besides the point.) It’s almost comical how easy it is to use:

DWORD PID = 1337; // something here

char buffer[MAX_PATH];
QueryFullProcessImageName(hProcess, 0, buffer, &value);
printf("EXE Path: %s\n", buffer);

Simple, right?

The only downside to this method is that you only get the full EXE path, nothing else. For more information, you might want to fill a PROCESSENTRY32 structure, which can be done in a few steps:

  1. Create a snapshot of all processes with CreateToolhelp32Snapshot()
  2. Iterate through all processes with Process32First() and Process32Next()

A source example of this would look like:

DWORD PID = 1337; // something here

HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, PID);
    peInfo.dwSize = sizeof(peInfo); // this line is REQUIRED
    BOOL nextProcess = Process32First(hSnapshot, &peInfo);
    bool found = false;
	if(peInfo.th32ProcessID == PID)
	    found = true;
	nextProcess= Process32Next(hSnapshot, &peInfo);

What is happening in this code sample is that a snapshot is being taken of the current processes in the system. If the iterated process has the desired PID, the process is examined. Information about a process is stored in the PROCESSENTRY32 structure. There are a lot of interesting pieces of information in that structure, but we are only concerned with the szExeFile field, which is the EXE name of the application. Note that it is only the application, not the full path, such as ‘itunes.exe’, not ‘C:\Program Files\iTunes\iTunes.exe’. If you want the full path, use the first solution presented above.

About samkerr

I'm an eclectic person. I like to dabble in a multitude of things. I'm sure you'll find my blog reflects that.
This entry was posted in Uncategorized. Bookmark the permalink.

8 Responses to A couple of different ways to get EXE name from PID in Windows

  1. Martin says:


    I’m trying to use the first solution but I’m being unable to access the function despite I included windows.h and defined _WIN32_WINNT as 0x0600 as it’s sad to be done in MSDN. What is lacking?

  2. samkerr says:

    Hi Martin,

    Thanks for reading! Are you running on Windows Vista or later? Are you trying to open a process you don’t have permission to? What error messages are you getting? You might have good luck by posting on http://www.stackoverflow.com.

  3. Martin says:


    You’re welcome. I’m running Windows 7, but notice that it’s not that the function is returning some kind of error. It’s simply not defined, despite I included the correct headers and set the correct #defines.

    And yep, I almost forgot about stackoverflow ๐Ÿ™‚

  4. ryk says:

    For future reference, the variable _WIN32_WINNT must be defined properly:

    Here is how I did it in Windows.h:

    /// edited TODOrsb
    #ifdef _CVI_
    #ifndef WINVER
    #ifndef _WIN32_WINNT
    #define _WIN32_WINNT _WIN32_WINNT_VISTA
    #ifndef _WIN32_WINDOWS
    /// end edited TODOrsb

    /// original section
    //#ifdef _CVI_
    //#ifndef WINVER
    //#define WINVER _WIN32_WINNT_WINXP
    //#ifndef _WIN32_WINNT
    //#define _WIN32_WINNT _WIN32_WINNT_WINXP
    //#ifndef _WIN32_WINDOWS
    //#define _WIN32_WINDOWS _WIN32_WINNT_WINXP
    /// end original section

  5. Stephan says:

    Or, simply type in cmd: tasklist /FI "PID eq 1337"

  6. Vanja says:

    A downside of otherwise neat function “QueryFullProcessImageName” is that if not running under administrator privileges, you cannot open a process running under SYSTEM account. Not even for basic information (OpenProcess with PROCESS_QUERY_LIMITED_INFORMATION). Since “QueryFullProcessImageName” needs the process handle, you’re stuck. I don’t know any other way to solve this situation other than “CreateToolhelp32Snapshot”.

  7. John says:

    Thanks a lot for sharing your research! Just a small note: In the first example, you forgot to include CloseHandle which means there is a resource leak (your app collects tons of open handles to the other process)…

    According to MSDN we should always close hProcess even when it’s 0 (invalid process). So wrap the code appropriately to ensure that CloseHandle always gets called after OpenProcess has been used.

    Anyway, thank you so much for sharing this technique! It’s way easier than the “enumerate every process and loop until we see the PID”.

    Oh, on a secondary note: “PROCESS_QUERY_INFORMATION” requires very high process privileges and will not work on protected processes (internet explorer, DRM media players, etc). To get the process path we only need limited privileges (as the QueryFullProcessImageName MSDN page explains), and we should therefore use “PROCESS_QUERY_LIMITED_INFORMATION” instead, but that new mode is not supported on XP or Server 2003. You can read the MSDN article “Process Security and Access Rights” in the section “Protected Processes” for more info, which says that Windows Vista introduced the enhanced security mode. So from Windows Vista and up we should always OpenProcess with the LIMITED query mode, to ensure we don’t get DENIED. ;-);

    Thanks again for all the help! I hope this helps you in return.

  8. samkerr says:

    Thanks for the great feedback John! Glad to hear you got some value out of this post that I wrote in 2012 ๐Ÿ™‚ The point about process privileges is a good one. I wonder if that was a requirement or when I wrote the entry, since I was poking around XP at that time.

Leave a Reply

Your email address will not be published. Required fields are marked *