在Rust中通过窗口句柄或进程ID获取Windows进程可执行路径
在Rust中使用windows crate获取进程可执行文件路径
问题背景
我需要在Windows系统中通过窗口句柄获取对应进程的可执行文件路径,预期流程是:
- 调用
GetWindowThreadProcessId()从窗口句柄提取进程ID - 通过
OpenProcess()获取目标进程的句柄 - 利用
GetModuleFileNameExW()(Unicode版本)获取可执行文件的完整路径
但最初在windows crate中找不到这些API,尝试过GetWindowModuleFileNameW()但它仅对当前进程或其子进程有效;不想为这个功能单独引入sysinfo crate,也希望使用仍在维护的windows crate而非winapi。
解决步骤
1. 启用windows crate的必要特性
OpenProcess()属于Win32_System_Threading特性,而GetModuleFileNameExW()需要启用Win32_System_ProcessStatus特性。在Cargo.toml中配置如下:
[dependencies.windows] version = "0.52" features = [ "Win32_Foundation", "Win32_System_Threading", "Win32_System_ProcessStatus", "Win32_GUI_WindowsAndMessaging" # 调用GetWindowThreadProcessId时需要 ]
2. 示例实现代码
use windows::core::PCWSTR; use windows::Win32::Foundation::{HANDLE, HWND, MAX_PATH}; use windows::Win32::System::ProcessStatus::GetModuleFileNameExW; use windows::Win32::System::Threading::{OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ}; use windows::Win32::GUI::WindowsAndMessaging::GetWindowThreadProcessId; fn get_process_path(hwnd: HWND) -> Option<String> { let mut pid = 0; unsafe { // 获取窗口对应的进程ID GetWindowThreadProcessId(hwnd, Some(&mut pid)); if pid == 0 { return None; } // 打开进程,获取具备必要权限的句柄 let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid); if process_handle.is_invalid() { return None; } // 读取进程可执行文件路径 let mut path_buf = [0u16; MAX_PATH as usize]; let path_len = GetModuleFileNameExW(process_handle, None, &mut path_buf); if path_len == 0 { return None; } // 将UTF-16缓冲区转换为String String::from_utf16(&path_buf[..path_len as usize]).ok() } }
关键说明
- 调用
OpenProcess()时必须传入PROCESS_QUERY_INFORMATION和PROCESS_VM_READ权限,否则GetModuleFileNameExW()会调用失败 Win32_System_ProcessStatus特性是获取GetModuleFileNameExW()的关键,之前找不到该函数就是因为未启用此特性- 如果需要ANSI版本的
GetModuleFileNameExA(),同样在Win32_System_ProcessStatus特性下可用,但推荐优先使用Unicode版本以支持全路径字符
内容的提问来源于stack exchange,提问作者dalvi
相关产品推荐
相关产品推荐

