웬디의 기묘한 이야기

글 작성자: WENDYS
반응형

How to get the process name from process id in C++

현재 실행 중인 프로세스 또는 외부 프로세스의 이름 정보를 얻어오는 방법들을 정리합니다.

MSDN을 참고하여 정리하였으며, MS에서 권장하는 각각의 방식들이 존재하기 때문에 그에 맞게 개발하면 됩니다.

 

 

현재 실행중인 프로세스 이름 정보를 획득하는 방법

현재 프로세스 정보를 획득하기 위해서는 별다른 정보가 필요 없습니다.

아주 간단하게 GetModuleFileName API를 이용하는 방법입니다.

 

https://docs.microsoft.com/ko-kr/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamew

 

GetModuleFileNameW function (libloaderapi.h) - Win32 apps

Retrieves the fully qualified path for the file that contains the specified module. The module must have been loaded by the current process.

docs.microsoft.com

 

#include <iostream>
#include <Windows.h>

int main() {

    wchar_t buffer[MAX_PATH] = {};
    if (GetModuleFileNameW(nullptr, buffer, MAX_PATH)) { // current HMODULE = nullptr
    std::wcout << L"current process name : " << buffer << std::endl;
    } 

    system("pause");
}

 

그렇다면 외부 프로세스 정보를 획득하려면 어떤 방법들이 있을까요??

 

1. GetModuleFileNameEx API를 이용하는 방법

가장 간단한 방법은 GetModuleFileNameEx API를 이용하는 방법으로 process handle 정보를 넣으면 process name 정보를 획득할 수 있는 방법입니다.

#include <iostream>
#include <Windows.h>
#include <Psapi.h>

int main() {

    DWORD process_id = GetCurrentProcessId();
    HANDLE process_handle = OpenProcess(
        PROCESS_QUERY_INFORMATION,
        FALSE,
        process_id
        );

    if (process_handle) {

        wchar_t buffer[MAX_PATH];
        if (GetModuleFileNameExW(process_handle, 0, buffer, MAX_PATH)) {
            std::wcout << L"process name : " << buffer << std::endl;
        }

        CloseHandle(process_handle);
    }

    system("pause");
}

하지만 이 방법에는 문제가 있습니다.

 

The GetModuleFileNameEx function is primarily designed for use by debuggers and similar applications that must extract module information from another process. If the module list in the target process is corrupted or is not yet initialized, or if the module list changes during the function call as a result of DLLs being loaded or unloaded, GetModuleFileNameEx may fail or return incorrect information.


MSDN 내용에 따르면 대상 프로세스의 모듈 목록이 손상되었거나, 아직 초기화되지 않았거나, DLL이 로드되거나 언로드 된 결과로 함수 호출 중에 모듈 목록이 변경되면 GetModuleFileNameEx API가 실패하거나 잘못된 정보를 리턴하게 된다고 합니다.

 

2. CreateToolhelp32Snapshot을 이용하는 방법

CreateToolhelp32Snapshot을 이용하는 경우 프로세스 목록을 순회하면서 PID와 일치하는 또는 실행 중인 모든 프로세스의 이름을 획득할 수 있습니다.

해당 방법은 OpenProcess를 하지 않고도 정보를 획득할 수 있는 방법이지만, 그만큼 획득할 수 있는 정보는 한정적입니다. 단순히 프로세스 이름만 획득하는 경우엔 그다지 적합해 보이지 않습니다.

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

int main() {
    
    const DWORD process_id = GetCurrentProcessId();
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE processes_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    if (INVALID_HANDLE_VALUE != processes_snapshot) {

        BOOL first = Process32First(processes_snapshot, &pe32);

        do {

            if (process_id == pe32.th32ProcessID) {
                std::wcout << "CreateToolhelp32Snapshot process name : " << pe32.szExeFile << std::endl;
                break;
            }

        } while (Process32Next(processes_snapshot, &pe32));

        CloseHandle(processes_snapshot);
    }
    
    system("pause");
}

 

 

3. 추천하는 방법은 QueryFullProcessImageName을 이용하는 방법

To retrieve the name of the main executable module for a remote process, use the GetProcessImageFileName or QueryFullProcessImageName function. This is more efficient and more reliable than calling the GetModuleFileNameEx function with a NULL module handle.


MSDN에서 추천하고 권장하는 방법입니다. 
사용 방법은 GetModuleFileNameEx처럼 간단하지만 더 효율적이고 안전한 방법이므로 해당 API 사용을 하는 게 좋습니다

#include <iostream>
#include <Windows.h>

int main() {

    DWORD process_id = GetCurrentProcessId();
    HANDLE process_handle = OpenProcess(
        PROCESS_QUERY_LIMITED_INFORMATION,
        FALSE,
        process_id
        );

    if (process_handle) {

        wchar_t buffer[MAX_PATH] = {};
        DWORD buffer_size = MAX_PATH;

        if (QueryFullProcessImageNameW(process_handle, 0, buffer, &buffer_size)) {
            std::wcout << L"QueryFullProcessImageNameW process name : " << buffer << std::endl;
        }

        CloseHandle(process_handle);
    }

    system("pause");
}

 

 

sample project download

 

get_process_name_from_process_id.zip
0.00MB

반응형