potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C++20&Win API プロセスのIDとパスを列挙する

Win32 APIEnumProcesses関数、QueryFullProcessImageNameW関数を使ってプロセスのIDとパスを列挙するサンプルコードです。

#include <string>
#include <memory>
#include <vector>

#define STRICT
#define NOMINMAX
#include <Windows.h>
#include <Psapi.h>

template <DWORD InitSize = 100, DWORD ExpandingSize = 100>
std::vector<DWORD> GetAllProcessIDs()
{
    std::vector<DWORD> processIds;

    for (DWORD size = InitSize;; size += ExpandingSize)
    {
        processIds.resize(size);
        DWORD cbNeeded;
        DWORD cbSize = size * sizeof(DWORD);
        if (!EnumProcesses(processIds.data(), cbSize, &cbNeeded))
        {
            return {};
        }
        if (cbNeeded < cbSize)
        {
            processIds.resize(cbNeeded / sizeof(DWORD));
            processIds.shrink_to_fit();
            return processIds;
        }
    }
}

struct unique_handle_deleter {
    inline void operator()(HANDLE h) const {
        CloseHandle(h);
    }
};
using unique_handle = std::unique_ptr<std::remove_pointer_t<HANDLE>, unique_handle_deleter>;

template <DWORD InitSize = 100, DWORD ExpandingSize = 100>
std::wstring QueryFullProcessImageNameW(HANDLE processHandle, DWORD flags)
{
    std::wstring s;
    for (DWORD size = InitSize;; size += ExpandingSize)
    {
        s.resize(size);
        DWORD cch = size;
        if (QueryFullProcessImageNameW(processHandle, flags, s.data(), &cch))
        {
            s.resize(cch);
            s.shrink_to_fit();
            return s;
        }
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        {
            return {};
        }
    }
}

#include <filesystem>
#include <format>
#include <iostream>

int main()
{
    for (auto processId : GetAllProcessIDs())
    {
        unique_handle processHandle(
            OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId));
        auto path = std::filesystem::path(QueryFullProcessImageNameW(processHandle.get(), 0));

        // プロセスID、ファイル名、場所
        std::wcout
            << std::format(L"{}, {}, {}", processId, path.filename().native(), path.parent_path().native())
            << std::endl;
    }

    return 0;
}