Windows系统下如何获取各进程打开的文件列表?
获取Windows进程已打开文件列表的代码改造
要在你现有代码基础上实现列出每个进程的已打开文件,需要借助Windows Native API扩展功能,同时处理进程权限问题。以下是改造后的完整方案:
核心改动说明
- 添加权限提升逻辑,获取
SE_DEBUG_NAME权限,否则无法访问系统级进程的句柄信息 - 使用
NtQuerySystemInformation(Windows原生API)获取全系统句柄数据 - 筛选目标进程的文件句柄,通过
GetFinalPathNameByHandle解析文件路径
改造后的完整代码
#include <cstdlib> #include <iostream> #include <cstring> #include <windows.h> #include <stdio.h> #include <tchar.h> #include <psapi.h> #include <winternl.h> // 链接所需系统库 #pragma comment(lib, "ntdll.lib") #pragma comment(lib, "psapi.lib") using namespace std; // 定义原生API的函数指针类型 typedef NTSTATUS(NTAPI* pNtQuerySystemInformation)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); // 提升进程权限 BOOL EnablePrivilege(LPCWSTR privilegeName) { HANDLE hToken; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValueW(NULL, privilegeName, &tp.Privileges[0].Luid)) { CloseHandle(hToken); return FALSE; } BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); CloseHandle(hToken); return result; } // 打印进程名称及已打开文件列表 void PrintProcessOpenFiles(DWORD processID) { TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>"); // 打开进程,请求必要权限 HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_DUP_HANDLE, FALSE, processID); if (NULL != hProcess) { // 获取进程名称 HMODULE hMod; DWORD cbNeeded; if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR)); } _tprintf(TEXT("\n%s (PID: %u)\n已打开文件:\n"), szProcessName, processID); // 获取NtQuerySystemInformation函数地址 pNtQuerySystemInformation NtQuerySystemInformation = (pNtQuerySystemInformation)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQuerySystemInformation"); if (!NtQuerySystemInformation) { _tprintf(TEXT("无法获取系统句柄信息接口\n")); CloseHandle(hProcess); return; } // 动态分配缓冲区存储系统句柄数据 ULONG bufferSize = 0x10000; PSYSTEM_HANDLE_INFORMATION handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(bufferSize); NTSTATUS status; // 自动扩容缓冲区直到容纳所有数据 while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, bufferSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) { bufferSize *= 2; handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, bufferSize); } if (!NT_SUCCESS(status)) { _tprintf(TEXT("获取系统句柄信息失败: 0x%X\n"), status); free(handleInfo); CloseHandle(hProcess); return; } // 遍历所有句柄,筛选目标进程的文件句柄 for (ULONG i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE_TABLE_ENTRY_INFO handleEntry = handleInfo->Handles[i]; if (handleEntry.UniqueProcessId != processID) { continue; } // 将目标进程的句柄复制到当前进程 HANDLE hDupHandle; if (!DuplicateHandle(hProcess, (HANDLE)handleEntry.Handle, GetCurrentProcess(), &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { continue; } // 判断是否为磁盘文件句柄 DWORD fileType = GetFileType(hDupHandle); if (fileType == FILE_TYPE_DISK) { TCHAR filePath[MAX_PATH]; // 获取文件规范化路径 DWORD pathLen = GetFinalPathNameByHandle(hDupHandle, filePath, MAX_PATH, FILE_NAME_NORMALIZED); if (pathLen > 0 && pathLen <= MAX_PATH) { _tprintf(TEXT(" %s\n"), filePath); } } CloseHandle(hDupHandle); } free(handleInfo); } else { _tprintf(TEXT("\n无法打开进程 (PID: %u)\n"), processID); } CloseHandle(hProcess); } int startup(void) { // 提升SE_DEBUG权限,否则无法访问部分系统进程 if (!EnablePrivilege(SE_DEBUG_NAME)) { _tprintf(TEXT("无法提升调试权限,部分进程信息无法获取\n")); } DWORD aProcesses[1024], cbNeeded, cProcesses; unsigned int i; if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) { return 1; } cProcesses = cbNeeded / sizeof(DWORD); // 遍历所有进程,打印其已打开文件 for (i = 0; i < cProcesses; i++) { if (aProcesses[i] != 0) { PrintProcessOpenFiles(aProcesses[i]); } } return 0; } int main(int argc, char** argv) { startup(); return 0; }
注意事项
- 代码必须以管理员权限运行,否则无法访问大部分系统进程
NtQuerySystemInformation是未公开的原生API,主流Windows 10/11版本均兼容,但后续系统版本可能有变动- 部分受保护的系统进程句柄无法复制,这类进程的文件列表会无法获取
内容的提问来源于stack exchange,提问作者mstoreysmith
相关产品推荐
相关产品推荐

