winapi - 使用给定的进程 ID 获取进程描述

我有一个使用 Toolhelp API 枚举所有进程的程序。使用我的 Sysinternals Process Explorer,我还可以看到所有进程的描述。此描述是否来自可执行文件?我如何得到它的名字?

这是我当前枚举进程的代码:

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <vector>
#include <system_error>
#include <memory>

using namespace std;

vector<PROCESSENTRY32W> getAllProcesses();

int main()
{
    for( PROCESSENTRY32W &pe : getAllProcesses() )
        wcout << pe.szExeFile << endl;
}

using XHANDLE = unique_ptr<void, decltype([]( HANDLE h ) { h && h != INVALID_HANDLE_VALUE && CloseHandle( h ); })>;

vector<PROCESSENTRY32W> getAllProcesses()
{
    auto throwSysErr = []() { throw system_error( (int)GetLastError(), system_category(), "error enumerating processes" ); };
    vector<PROCESSENTRY32W> processes;
    XHANDLE xhSnapshot( CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) );
    if( xhSnapshot.get() == INVALID_HANDLE_VALUE )
        throwSysErr();;
    PROCESSENTRY32W pe;
    pe.dwSize = sizeof pe;
    if( !Process32FirstW( xhSnapshot.get(), &pe ) )
        throwSysErr();
    for( ; ; )
    {
        processes.emplace_back( pe );
        pe.dwSize = sizeof pe;
        if( !Process32NextW( xhSnapshot.get(), &pe ) )
            if( GetLastError() == ERROR_NO_MORE_FILES )
                break;
            else
                throwSysErr();
    }
    return processes;
}

回答1

@RemyLebeau 的代码实现方式改编自 https://docs.microsoft.com/en-us/windows/win32/api/winver/nf-winver-verqueryvaluea#examples 文档示例。正如 https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess#parameters 所说,

如果指定的进程是系统空闲进程(0x00000000),函数失败,最后一个错误码是ERROR_INVALID_PARAMETER。如果指定的进程是系统进程或客户端服务器运行时子系统 (CSRSS) 进程之一,则此函数将失败,最后一个错误代码为 ERROR_ACCESS_DENIED,因为它们的访问限制阻止了用户级代码打开它们。

int main()
{
    TCHAR szFile[MAX_PATH] = {};
    DWORD dwSize = MAX_PATH;

    for (PROCESSENTRY32W& pe : getAllProcesses())
    {
        wcout << pe.szExeFile << endl;

        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
            FALSE, pe.th32ProcessID);
        if (hProcess == NULL)
        {
            //ErrorExit(TEXT("OpenProcess"));
        }
        else
        {
            memset(szFile, 0, MAX_PATH);
            dwSize = MAX_PATH;
            QueryFullProcessImageName(hProcess,0, szFile,&dwSize);
            DWORD s = GetFileVersionInfoSize(szFile,NULL);
            if (s != 0)
            {
                LPVOID lpData = HeapAlloc(GetProcessHeap(), 0, s);
                GetFileVersionInfo(szFile,0,s, lpData);

                HRESULT hr;
                UINT cbTranslate;
                struct LANGANDCODEPAGE {
                    WORD wLanguage;
                    WORD wCodePage;
                } *lpTranslate;

                // Read the list of languages and code pages.

                VerQueryValue(lpData,
                    TEXT("\\VarFileInfo\\Translation"),
                    (LPVOID*)&lpTranslate,
                    &cbTranslate);

                // Read the file description for each language and code page.
                LPVOID lpBuffer;
                UINT dwBytes;
                for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
                {
                    TCHAR SubBlock[255] = {};
                    hr = StringCchPrintf(SubBlock, 50,
                        TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
                        lpTranslate[i].wLanguage,
                        lpTranslate[i].wCodePage);
                    if (FAILED(hr))
                    {
                        // TODO: write error handler.
                    }

                    // Retrieve file description for language and code page "i". 
                    VerQueryValue(lpData,
                        SubBlock,
                        &lpBuffer,
                        &dwBytes);

                    wcout << (TCHAR*)(lpBuffer) << endl;
                }
                HeapFree(GetProcessHeap(), 0, lpData);
            }
            //GetProcessImageFileName(hProcess, szFile, dwSize);
        }

    }
}

相似文章

最新文章