获取全屏进程名时GetModuleBaseNameA返回错误5(ACCESS_DENIED),求低权限方法
问题描述
我尝试获取处于全屏模式运行的进程名称,但打开任意游戏并执行以下代码时,即使以管理员权限运行,GetLastError()仍返回错误5(ACCESS_DENIED)。我推测这是由反作弊机制导致的,但我仅需要获取进程名称,请问是否存在所需权限更低的获取方法?
#include <windows.h> #include <psapi.h> HWND hwnd = GetForegroundWindow(); char name_buffer[256] = ""; int buffer_size = 256; if (!hwnd) { strncpy(name_buffer, "No fullscreen app detected", buffer_size - 1); name_buffer[buffer_size - 1] = '\0'; return; } RECT window_rect; GetWindowRect(hwnd, &window_rect); int screen_width = GetSystemMetrics(SM_CXSCREEN); int screen_height = GetSystemMetrics(SM_CYSCREEN); if((window_rect.right - window_rect.left) >= screen_width && (window_rect.bottom - window_rect.top) >= screen_height){ DWORD process_id; GetWindowThreadProcessId(hwnd, &process_id); HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_id); if (process_handle) { if (GetModuleBaseNameA(process_handle, NULL, name_buffer, buffer_size) == 0) { obs_log(LOG_ERROR, "Failed to get module base name: %lu", GetLastError()); strncpy(name_buffer, "Unknown", buffer_size - 1); name_buffer[buffer_size - 1] = '\0'; } CloseHandle(process_handle); } else { strncpy(name_buffer, "OpenProcess failed", buffer_size - 1); name_buffer[buffer_size - 1] = '\0'; } }
解决方案
以下几种方法可在更低权限下获取进程名称,避开反作弊的权限拦截:
直接获取窗口标题
多数全屏游戏的窗口标题包含进程名称(或可映射到进程名),无需打开进程句柄。调用GetWindowTextA即可,该API仅需窗口访问权限,通常不会被反作弊拦截。修改示例:
if((window_rect.right - window_rect.left) >= screen_width && (window_rect.bottom - window_rect.top) >= screen_height){ // 用窗口标题替代进程名 if (!GetWindowTextA(hwnd, name_buffer, buffer_size)) { strncpy(name_buffer, "Unknown Window", buffer_size - 1); name_buffer[buffer_size - 1] = '\0'; } }使用宽松权限打开进程并查询路径
若需获取进程可执行文件名,可尝试用PROCESS_QUERY_LIMITED_INFORMATION权限打开进程——该权限比PROCESS_QUERY_INFORMATION更宽松,多数场景下不会被反作弊拒绝。随后调用QueryFullProcessImageNameA获取路径,再从路径中提取文件名作为进程名。修改示例:
if((window_rect.right - window_rect.left) >= screen_width && (window_rect.bottom - window_rect.top) >= screen_height){ DWORD process_id; GetWindowThreadProcessId(hwnd, &process_id); // 使用PROCESS_QUERY_LIMITED_INFORMATION权限 HANDLE process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id); if (process_handle) { char path_buffer[MAX_PATH] = ""; DWORD path_len = MAX_PATH; if (QueryFullProcessImageNameA(process_handle, 0, path_buffer, &path_len)) { // 从路径中提取文件名 char* filename = strrchr(path_buffer, '\\'); if (filename) { strncpy(name_buffer, filename + 1, buffer_size - 1); } else { strncpy(name_buffer, path_buffer, buffer_size - 1); } name_buffer[buffer_size - 1] = '\0'; } else { strncpy(name_buffer, "Unknown", buffer_size - 1); name_buffer[buffer_size - 1] = '\0'; } CloseHandle(process_handle); } else { strncpy(name_buffer, "OpenProcess failed", buffer_size - 1); name_buffer[buffer_size - 1] = '\0'; } }通过WMI查询进程信息
借助Windows的WMI服务,查询Win32_Process类中对应PID的进程名称。这种方式无需直接打开进程句柄,通过系统服务获取信息,权限要求更低,但调用逻辑相对复杂,适合对性能要求不高的场景。
内容的提问来源于stack exchange,提问作者sfinaecpp
相关产品推荐
相关产品推荐

