注册 登录
编程论坛 C语言论坛

windows遍历进程的方法

a451410 发布于 2024-12-20 21:34, 451 次点击
请问在windows10/11系统中,有几种方式可以遍历当前进程,都是那些API?
不是那种自己通过ring0获得的进程,而是正儿八经通过微软提供的api可以获取到的方式,
能帮我列出遍历方式的关键函数吗?不尽感激
1 回复
#2
时光流逝2025-03-24 20:46
1. 使用CreateToolhelp32Snapshot、Process32First和Process32Next

程序代码:
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

int main() {
    PROCESSENTRY32 pe32{};
    pe32.dwSize = sizeof(PROCESSENTRY32);

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hProcessSnap) {
        return 0;
    }

    BOOL bRet = Process32First(hProcessSnap, &pe32);
    while (bRet) {
        wprintf(L"Process ID: %lu, Process Name: %ws\n", pe32.th32ProcessID, pe32.szExeFile);
        bRet = Process32Next(hProcessSnap, &pe32);
    }
    CloseHandle(hProcessSnap);
    return 0;
}


2. 使用NtQuerySystemInformation
程序代码:
#include <windows.h>
#include <winternl.h>
#include <stdio.h>

typedef NTSTATUS(NTAPI* pNtQuerySystemInformation)(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength
);

int main() {
    pNtQuerySystemInformation NtQuerySystemInformation =
        (pNtQuerySystemInformation)GetProcAddress(
            GetModuleHandleW(L"ntdll.dll"),
            "NtQuerySystemInformation"
        );

    SYSTEM_PROCESS_INFORMATION* spi = nullptr;
    ULONG bufferSize = 0x1000;
    NTSTATUS status;

    do {
        bufferSize *= 2;
        spi = (SYSTEM_PROCESS_INFORMATION*)malloc(bufferSize);
        if (!spi) {
            return 0;
        }
        status = NtQuerySystemInformation(
            SystemProcessInformation,
            spi,
            bufferSize,
            nullptr
        );
        if (status == STATUS_INFO_LENGTH_MISMATCH) {
            free(spi);
            spi = nullptr;
        }
    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    if (NT_SUCCESS(status)) {
        SYSTEM_PROCESS_INFORMATION* current = spi;
        while (current) {
            wprintf(L"Process ID: %lu, Process Name: %ws\n",
                current->UniqueProcessId,
                current->ImageName.Buffer);
            current = (SYSTEM_PROCESS_INFORMATION*)((BYTE*)current + current->NextEntryOffset);
        }
    }
    free(spi);
    return 0;
}


3. 使用EnumProcesses、OpenProcess、GetModuleFileNameEx
程序代码:
#include <windows.h>
#include <psapi.h>
#include <stdio.h>

int main() {
    DWORD pProcess[1024];
    DWORD cbNeeded;
    DWORD cProcesses;

    if (!EnumProcesses(pProcess, sizeof(pProcess), &cbNeeded)) {
        return 0;
    }

    cProcesses = cbNeeded / sizeof(DWORD);

    for (int index = 0; index < cProcesses; index++) {
        HANDLE hProcess = OpenProcess(
            PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
            FALSE,
            pProcess[index]
        );
        if (hProcess == NULL) {
            continue;
        }

        char szModName[MAX_PATH];
        if (GetModuleFileNameEx(hProcess, NULL, szModName, sizeof(szModName))) {
            printf("Process ID: %lu, Process Path: %s\n", pProcess[index], szModName);
        }

        CloseHandle(hProcess);
    }
    return 1;
}

4.WMI查询(这种方法在c语言上的实现比较复杂,但在一些脚本型语言如vbs,vb6上非常简便,这里就不放了)
其中NtQuerySystemInformation获取到的进程信息最全面,包括进程的创建时间和优先级等等,Process32First+Process32Next最容易获取进程列表,信息比较全面,而EnumProcesses纯废物,还得通过OpenProcess打开进程才能获取除PID外的信息,WMI...不好说
1