ぷるぷるの雑記

低レイヤーがんばるぞいなブログ. 記事のご利用は自己責任で.

Windowsでプロセス名からpidを検索する

C/C++のプログラムにおいてプロセス名からpidを取得するプログラムを作りました.

環境

項目 説明
OS Windows11
Visual Studio 17.6.2(2022)

ソースコード

以下は「chrome.exe」というプロセスのプロセス識別子を表示するためのソースコードです.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
#include <vector>

/* 表示用 */
#include<iostream>

using namespace std;

void GetPidByName(const TCHAR *targetName, vector<DWORD>& ret)
{
    /* システム内のプロセス識別子を取得 */
    DWORD pids[1024], byteNeeded;

    if (!EnumProcesses(pids, sizeof(pids), &byteNeeded))
    {
        return;
    }

    /* プロセスの総数を計算 */
    DWORD processNum;
    processNum = byteNeeded / sizeof(DWORD);

    /* 各プロセスごとにループ */
    for (unsigned int i = 0; i < processNum; ++i) {

        DWORD pid = pids[i];

        /* プロセス識別子からプロセスハンドル取得 */
        HANDLE hProcess = OpenProcess(
            PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
            FALSE, 
            pid
        );

        if (NULL != hProcess)
        {
            HMODULE hMod;
            DWORD cbNeeded;
            TCHAR processName[MAX_PATH];

            /* 本来はhModは配列にすべきだがプロセス名さえ取得できれば十分とする */
            if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
            {
                /* プロセス名取得 */
                GetModuleBaseName(
                    hProcess, 
                    hMod, 
                    processName,
                    sizeof(processName) / sizeof(TCHAR)
                );

                /* プロセス名が一致するか */
                if (!_tcscmp(targetName, processName)) {
                    ret.push_back(pid);
                }
            }

            /* ハンドルクローズ */
            CloseHandle(hProcess);
        }
    }

}


int main(void)
{
    /* 結果を入れるベクタ */
    vector<DWORD> pids;

    /* プロセス名からpidを検索 */
    GetPidByName(TEXT("chrome.exe"), pids);

    /* pidを表示 */
    for (const DWORD pid : pids) {
        cout << pid << endl;
    }

    return 0;
}

// 実行結果(例)
19212
19252
19452
18492
18684
18588
20624
7156
22944
22668
14912
17884
20672
11160
22356
23096
22132
10768
9800
15228
7632
260
10724
21760
10568

解説

当然ながらWinAPIのオンパレードです. まず EnumProcessModules() を用いてシステム内のプロセス識別子をDWORDの配列に格納します. その次に OpenProcess() でプロセス識別子に対応したプロセスへのハンドルを取得、 EnumProcessModules() を用いてそのプロセス内の(最初の)モジュールへのハンドルを取得、最後に GetModuleBaseName() をコールしてモジュールの名前を取得します.

実行ファイル名とプロセス(モジュール)名は必ずしも一致しないので注意が必要です.

参考

learn.microsoft.com

learn.microsoft.com

learn.microsoft.com

www.t-net.ne.jp