如何在Rust中获取所有可见窗口对应的进程文件名?
问题分析与修复方案
核心错误:错误获取进程ID
你的调用代码中,GetWindowThreadProcessId的使用完全错误:该函数返回值是窗口所属的线程ID,而进程ID需要通过第二个指针参数输出。你传入ptr::null_mut()导致根本没拿到正确的进程ID,反而把线程ID传给了get_file_name_from_process_id,自然无法打开进程,返回None。
修复后的调用代码
// 正确获取进程ID let mut pid = 0; GetWindowThreadProcessId(hwnd, &mut pid); let file_name: String = get_file_name_from_process_id(pid).unwrap_or("default".to_string());
修复get_file_name_from_process_id函数的其他问题
除了进程ID的错误,原函数还有两个关键问题:
- 缓冲区初始化错误:
Vec::with_capacity仅预留内存但未设置实际长度,导致WinAPI函数无法写入数据 - 权限问题:部分系统进程无法用
PROCESS_QUERY_INFORMATION打开,建议使用更宽松的PROCESS_QUERY_LIMITED_INFORMATION权限
修复后的函数代码:
use std::ffi::{OsString, OsStr}; use std::os::windows::ffi::OsStringExt; use std::path::Path; use std::ptr; use winapi::um::handleapi::CloseHandle; use winapi::um::processthreadsapi::{OpenProcess, GetWindowThreadProcessId}; use winapi::um::psapi::QueryFullProcessImageNameW; use winapi::um::winnt::PROCESS_QUERY_LIMITED_INFORMATION; unsafe fn get_file_name_from_process_id(pid: u32) -> Option<String> { // 使用兼容性更好的PROCESS_QUERY_LIMITED_INFORMATION权限 let process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid); if process_handle.is_null() { return None; } // 第一次调用获取所需缓冲区大小 let mut size: u32 = 0; if QueryFullProcessImageNameW(process_handle, 0, ptr::null_mut(), &mut size) == 0 { let err = std::io::Error::last_os_error(); // ERROR_INSUFFICIENT_BUFFER是预期错误,说明需要分配缓冲区 if err.raw_os_error() != Some(0x7A) { CloseHandle(process_handle); return None; } } // 初始化足够大小的缓冲区(包含终止符) let mut buffer = vec![0u16; size as usize]; // 第二次调用获取进程路径 if QueryFullProcessImageNameW(process_handle, 0, buffer.as_mut_ptr(), &mut size) == 0 { CloseHandle(process_handle); return None; } // 转换为OsString并截断到实际有效长度 let process_path = OsString::from_wide(&buffer[..size as usize]); // 提取文件名 let file_name = process_path.as_os_str() .and_then(OsStr::to_str) .and_then(|s| Path::new(s).file_name()) .and_then(|s| s.to_str()) .map(|s| s.to_string()); CloseHandle(process_handle); file_name }
额外注意事项
- 对于
csrss.exe、wininit.exe等系统核心进程,即使使用管理员权限也可能无法获取路径,这是Windows的安全限制 - 必须确保关闭进程句柄,避免资源泄漏
- 可取消注释错误打印语句(代码中被注释的部分),帮助排查特定进程的获取失败原因
内容的提问来源于stack exchange,提问作者m0ke0
相关产品推荐
相关产品推荐

