Updates
- Examples:
- https://github.com/DoumanAsh/clipboard-win
- https://github.com/DoumanAsh/windows-win-rs
- The above are both OO-like wrapper on top of winapi.
- You can find in crates.io category. but not very accessible:
- https://crates.io/categories/os::windows-apis
- Currently, no category index page available in crates.io. There's no easy links.
The original post
I'm porting my small python script that calls win32api into rust.
Are there any safe/ergonomic wrapper for winapi
?
Here's a very little version of my own:
#[allow(dead_code)]
#[allow(non_snake_case)]
mod winwrap {
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
pub use winapi::shared::minwindef::*;
pub use winapi::shared::ntdef::*;
pub use winapi::shared::windef::*;
use winapi::um::processthreadsapi;
use winapi::um::psapi;
use winapi::um::winuser;
const LEN: usize = 1024;
fn slice_to_os_string_trancate_nul(text: &[u16]) -> OsString {
if let Some(new_len) = text.iter().position(|x| *x == 0) {
OsString::from_wide(&text[0..new_len])
} else {
OsString::from_wide(&text)
}
}
///
pub fn GetForegroundWindow() -> HWND {
unsafe { winuser::GetForegroundWindow() }
}
/// returns `OsString`, nul char is truncated.
pub fn GetWindowTextW(hwnd: HWND) -> OsString {
let text_len = unsafe { winuser::GetWindowTextLengthW(hwnd) };
// println!("text_len: {}", text_len);
let mut text = vec![0u16; (text_len + 1) as usize];
unsafe {
winuser::GetWindowTextW(hwnd, text.as_mut_ptr(), text_len + 1);
}
slice_to_os_string_trancate_nul(&text)
}
/// returns `(thread_id, proc_id)`
pub fn GetWindowThreadProcessId(hwnd: HWND) -> (DWORD, DWORD) {
let mut proc_id: DWORD = 0;
let thread_id = unsafe { winuser::GetWindowThreadProcessId(hwnd, &mut proc_id) };
(thread_id, proc_id)
}
/// returns process handle.
pub fn OpenProcess(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE {
unsafe { processthreadsapi::OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId) }
}
/// returns `OsString`, nul char is truncated.
pub fn GetProcessImageFileNameW(hProcess: HANDLE) -> OsString {
let mut image_file_name = vec![0u16; LEN];
let _ = unsafe {
psapi::GetProcessImageFileNameW(
hProcess,
image_file_name.as_mut_ptr(),
image_file_name.len() as u32,
)
};
slice_to_os_string_trancate_nul(&image_file_name)
}
}
Caller site looks like this:
let hwnd = winwrap::GetForegroundWindow();
println!("hwnd: {:?}", hwnd);
let text = winwrap::GetWindowTextW(hwnd);
println!("text: {:?}", text);
let (thread_id, proc_id) = winwrap::GetWindowThreadProcessId(hwnd);
println!("thread_id: {}", thread_id);
println!("proc_id: {}", proc_id);
let h_process = winwrap::OpenProcess(
PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
FALSE,
proc_id,
);
println!("h_process: {:?}", h_process);
let image_file_name = winwrap::GetProcessImageFileNameW(h_process);
println!("image_file_name: {:?}", image_file_name);
Output:
hwnd: 0x809aa
text: "MINGW64:/c/workmx3/src/winlog"
thread_id: 9684
proc_id: 9680
h_process: 0x3c
image_file_name: "\\Device\\HarddiskVolume3\\Program Files\\Git\\usr\\bin\\mintty.exe"