遍歷系統進程經常使用的有三種方式windows
<Tlhelp32.h>
,先使用CreateToolhelp32Snapshot
建立系統快照,即拷貝一份系統全部進程的信息到指定的結構體PROCESSENTRY32
中,而後使用Process32First
和Process32Next
得到每個進程的詳細信息。須要注意的是編譯成32位程序只能獲取32位進程的詳細信息,編譯成64位則能獲取全部進程的詳細信息<psapi.h>
,先使用EnumProcesses
獲取系統全部的進程PID,而後用EnumProcessModules
遍歷每一個進程中的模塊,最後用GetModuleFileNameEx
獲取模塊的完整路徑或者用GetModuleBaseName
獲取模塊的名稱。也須要注意程序編譯的位數與進程的位數NtQuerySystemInformation
,因爲是未公開函數因此須要自定義函數原型。留個坑之後填完整思路
(1).使用CreateToolhelp32Snapshot
以及傳參TH32CS_SNAPPROCESS
建立系統進程快照
(2).使用Process32First
獲取第一個進程的信息存入到PROCESSENTRY32
結構體中
(3).再用Process32Next
遍歷全部進程
(4).最後用CloseHandle
關閉句柄api
注意事項
程序很簡單,須要注意的是編碼問題,包括控制檯輸出的編碼以及程序自己的編碼,windows.h
頭文件也定義許多保證編碼兼容性的變量,好比TEXT()
_T
TCHAR
LPTSTR...
函數
-fexec-charset=gbk
wchar_t *ws = L"你好"; wprintf(L"%s\n",ws)
TCHAR
遇到寬字符就是Unicode
編碼,不然就是char
類型,TEXT()
_T()
_tprintf
等函數同理<locale.h>
和<tchar.h>
,可能須要添加代碼setlocale(LC_ALL,"chs");
完整Demoui
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <Tlhelp32.h> int main(int argc, char *argv[]) { PROCESSENTRY32 pe32; pe32.dwSize = sizeof(pe32); HANDLE hSnapshot_proc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot_proc != INVALID_HANDLE_VALUE) { BOOL check = Process32First(hSnapshot_proc, &pe32); while (check) { printf("進程PID = %d 進程名 = %s\n", pe32.th32ProcessID, pe32.szExeFile); check = Process32Next(hSnapshot_proc, &pe32); } } CloseHandle(hSnapshot_proc); system("pause"); return 0; }
編譯命令gcc -fexec-charset=gbk proc1.c -o proc1
編碼
運行截圖spa
完整思路
(1).使用EnumProcesses
獲取全部進程PID
(2).獲取當前進程的Debug
權限
(3).使用OpenProcess
打開進程,依次獲取全部進程的進程句柄
(4).根據進程句柄以及EnumProcessModules
遍歷進程的全部模塊
(5).使用GetModuleFileNameEx
獲取進程的完整路徑
(6).使用CloseHandle
關閉句柄以及取消Debug
權限code
注意事項
使用EnumProcesses
須要注意四個坑,先說明一下我是用的MinGW
編譯器,用 VScode 寫完代碼本身調 gcc 編譯!orm
<psapi.h>
必定要在<windows.h>
以後-lpsapi
必定要在文件名proc3.c
以後OpenProcess
前必定要獲取Debug
權限完整Demotoken
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <psapi.h> BOOL SetProcessPrivilege(char *lpName, BOOL opt); int main(int argc, char *argv[]) { DWORD Proc_pid[1024], Retn_bytes, Proc_count, Retn_bytes2; unsigned int i; HMODULE hMod[1024]; HANDLE hProcess; char szModName[MAX_PATH]; if (EnumProcesses(Proc_pid, sizeof(Proc_pid), &Retn_bytes)) { Proc_count = Retn_bytes / sizeof(DWORD); SetProcessPrivilege("SeDebugPrivilege", 1); for (i = 0; i < Proc_count; i++) { hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Proc_pid[i]); if (hProcess != NULL) { EnumProcessModules(hProcess, hMod, sizeof(hMod), &Retn_bytes2); GetModuleFileNameEx(hProcess, hMod[0], szModName, sizeof(szModName)); printf("PID=%d Path=%s\n", Proc_pid[i], szModName); } CloseHandle(hProcess); } SetProcessPrivilege("SeDebugPrivilege", 0); } system("pause"); return 0; } BOOL SetProcessPrivilege(char *lpName, BOOL opt) { HANDLE tokenhandle; TOKEN_PRIVILEGES NewState; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenhandle)) { LookupPrivilegeValue(NULL, lpName, &NewState.Privileges[0].Luid); NewState.PrivilegeCount = 1; NewState.Privileges[0].Attributes = opt != 0 ? 2 : 0; AdjustTokenPrivileges(tokenhandle, FALSE, &NewState, sizeof(NewState), NULL, NULL); CloseHandle(tokenhandle); return 1; } else { return 0; } }
編譯命令gcc proc3.c -lpsapi -o proc3
接口
運行截圖