2

I'm trying to get the name of processes which have a visible window. For example, if I have Chrome opened, I would like to get the string "chrome.exe", but I only get the init value "unknown" using the code below.

I read around it could be an access rights problem, can you suggest me how to change them in order to get the name of processes?

DWORD idProc = 0;       //pointer to the process which created the window
DWORD idThread = GetWindowThreadProcessId(Wnd->get_handle(), &idProc);
Wnd->set_pid(idThread); //Wnd is an object of a class i created, to collect processes info
// Get a handle to the process.
TCHAR szProcessName[DEFAULT_BUFLEN] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
    PROCESS_VM_READ,
    FALSE, idProc);

if (hProcess!=NULL) {
    HMODULE hMod;
    DWORD cbNeeded;
    if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
        &cbNeeded))
    {
        GetModuleBaseName(hProcess, hMod, szProcessName,        
            sizeof(szProcessName) / sizeof(TCHAR));
    }
}
Wnd->set_processname(szProcessName);                            
CloseHandle(hProcess);

It works fine for some processes, but it doesn't for many others like Chrome, as I said.

EDIT: I forgot to say, I've just filtered visible windows, so suppose handles are what I need yet.

Varad Chemburkar
  • 458
  • 2
  • 6
  • 15
Serusar
  • 57
  • 6
  • You need to add error checking so that you can tell which call(s) failed. – Harry Johnston Dec 01 '16 at 20:23
  • https://wj32.org/wp/2010/03/30/get-the-image-file-name-of-any-process-from-any-user-on-vista-and-above/ – RbMm Dec 01 '16 at 20:38
  • Ok, thanks for the answer first. I added some std::cout< – Serusar Dec 01 '16 at 21:05
  • 2
    The [documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682631.aspx) says: "*If this function is called from a 32-bit application running on WOW64, it can only enumerate the modules of a 32-bit process. If the process is a 64-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).*" – Remy Lebeau Dec 01 '16 at 21:25
  • 2
    In any case, you are passing the window's **thread id** to `Wnd->set_pid()` when you should be passing its **process id** instead. Also, you should replace `EnumProcessModules()`/`GetModuleBaseName()` with either `GetModuleFileNameEx()`, `GetProcessImageFileName()`, or `QueryFullProcessImageName()` instead (the latter two work with `PROCESS_QUERY_LIMITED_INFORMATION`, which you are more likely to get access to than `PROCESS_QUERY_INFORMATION`). – Remy Lebeau Dec 01 '16 at 21:25
  • So i should replace even EnumProcessModules() with someone of those functions? By the way, i pass idThread just cause if i open 2 folders they will get the same process id (which is correct) but i need to get 2 different values for each of them (and idThread does it). – Serusar Dec 01 '16 at 21:35
  • Error checking doesn't mean calling GetLastError. You have to red the docs. For each function. Typically you'll need to check return value. – David Heffernan Dec 02 '16 at 05:56

2 Answers2

0

this question how get process name/path by ID - is many time already answered here.

if you need name only (but not full path) - you can use CreateToolhelp32Snapshot / Process32First / Process32Next compare PROCESSENTRY32.th32ProcessID with your idProc and use PROCESSENTRY32.szExeFile.

alternate and more effective way use ZwQuerySystemInformation with SystemProcessInformation info class.compare SYSTEM_PROCESS_INFORMATION.UniqueProcessId with your idProc and use SYSTEM_PROCESS_INFORMATION.ImageName. really first way is shell over this method.

if you need not only name, but full path :

if you have SE_DEBUG_PRIVILEGE - you need enable it, open process with PROCESS_QUERY_LIMITED_INFORMATION (vista+) or PROCESS_QUERY_INFORMATION (xp/2003) and use ZwQueryInformationProcess with ProcessImageFileName (return path in NT form) or GetProcessImageFileName (internally it call ZwQueryInformationProcess(,ProcessImageFileName,))

or begin from vista - you can use ProcessImageFileNameWin32 (return win32-path) or QueryFullProcessImageName (again only documented thin shell over this way)

also begin from vista - most effective way query process full path (in NT form) - use ZwQuerySystemInformation with SystemProcessIdInformation info class. this way not require any privileges and open process

RbMm
  • 31,280
  • 3
  • 35
  • 56
0

use GetProcessImageNamr API instead:

#include <iostream>
using namespace std;
#include <windows.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")


int main()
{

    DWORD dwProcessId;
    DWORD dwThreadId ;

    while(1)
    {
        Sleep(2000);
        HWND hForg = GetForegroundWindow(); // to get the foreground windows' handle window
        dwThreadId = GetWindowThreadProcessId(hForg, &dwProcessId); // getting the window's process ID

        DWORD dwDesiredAccess =
            PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
        bool bInheritHandle = false;
        HANDLE hProcess = OpenProcess(dwDesiredAccess,
                                bInheritHandle, dwProcessId);
        if(INVALID_HANDLE_VALUE == hProcess)
            cout << "Failed to open process!" << endl;

        HINSTANCE hMod = (HINSTANCE)GetWindowLongPtr(hForg, GWLP_HINSTANCE);
        if(!hMod)
            cout << "Null Module!" << endl;
        char szModFileName[MAX_PATH] = "";  

    //  never use this cause it won't get you what you want
    //  GetModuleFileNameEx(hProcess, hMod, szModFileName, MAX_PATH);

    //  use this
        GetProcessImageFileName(hProcess, szModFileName, MAX_PATH);

        CloseHandle(hProcess);

        char szWindowName[MAX_PATH] = "";
        GetWindowText(hForg, szWindowName, MAX_PATH);
        cout << "Window Name: " << szWindowName << endl;
        cout << "Created by: " << szModFileName << endl << endl;

    }


    cout << endl << endl << endl;
    return 0;
}
  • don't use GetModuleFileNameEx but use GetProcessImageFileName
Raindrop7
  • 3,889
  • 3
  • 16
  • 27
  • `PROCESS_QUERY_INFORMATION | PROCESS_VM_READ` - this is error. main we not need `PROCESS_VM_READ`. and begin from vista we need use `PROCESS_QUERY_LIMITED_INFORMATION` in place `PROCESS_QUERY_INFORMATION` – RbMm Dec 01 '16 at 22:14
  • Why _don't use `GetModuleFileNameEx` but use `GetProcessImageFileName`_? For me they produce same results. Only difference is the path in drive letters form, rather than device. – Salvador Jan 30 '17 at 20:49