120 lines
3.3 KiB
Rust
120 lines
3.3 KiB
Rust
use windows::{
|
|
core::*,
|
|
Win32::Foundation::{HWND, LPARAM},
|
|
Win32::UI::WindowsAndMessaging::{
|
|
EnumWindows, GetForegroundWindow, GetWindowTextW, GetWindowTextLengthW,
|
|
GetWindowThreadProcessId, IsWindowVisible,
|
|
},
|
|
Win32::System::Threading::{OpenProcess, QueryFullProcessImageNameW, PROCESS_QUERY_INFORMATION, PROCESS_NAME_WIN32},
|
|
};
|
|
use serde::Serialize;
|
|
use serde_json;
|
|
|
|
#[derive(Serialize)]
|
|
struct WindowInfo {
|
|
hwnd: String,
|
|
title: String,
|
|
pid: u32,
|
|
process_name: String,
|
|
is_active: bool,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
struct WindowList {
|
|
active_window: Option<WindowInfo>,
|
|
all_windows: Vec<WindowInfo>,
|
|
}
|
|
|
|
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
|
unsafe {
|
|
// 获取当前激活窗口
|
|
let active_hwnd = GetForegroundWindow();
|
|
let active_info = if !active_hwnd.is_invalid() {
|
|
Some(get_window_info(active_hwnd))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// 获取所有窗口
|
|
let mut all_windows: Vec<WindowInfo> = Vec::new();
|
|
|
|
EnumWindows(
|
|
Some(enum_windows_callback),
|
|
LPARAM(&mut all_windows as *mut Vec<WindowInfo> as isize),
|
|
)?;
|
|
|
|
let result = WindowList {
|
|
active_window: active_info,
|
|
all_windows,
|
|
};
|
|
|
|
let json = serde_json::to_string_pretty(&result)
|
|
.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;
|
|
println!("{}", json);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
unsafe fn get_window_info(hwnd: HWND) -> WindowInfo {
|
|
// 获取窗口标题
|
|
let len = GetWindowTextLengthW(hwnd);
|
|
let title = if len > 0 {
|
|
let mut buffer = vec![0u16; len as usize + 1];
|
|
let actual_len = GetWindowTextW(hwnd, &mut buffer);
|
|
if actual_len > 0 {
|
|
String::from_utf16_lossy(&buffer[..actual_len as usize])
|
|
} else {
|
|
String::new()
|
|
}
|
|
} else {
|
|
String::new()
|
|
};
|
|
|
|
// 获取进程ID
|
|
let mut pid: u32 = 0;
|
|
GetWindowThreadProcessId(hwnd, Some(&mut pid));
|
|
|
|
// 获取进程名称
|
|
let process_name = get_process_name(pid).unwrap_or_else(|_| String::from("Unknown"));
|
|
|
|
// 检查是否为激活窗口
|
|
let is_active = hwnd == GetForegroundWindow();
|
|
|
|
WindowInfo {
|
|
hwnd: format!("{:?}", hwnd.0),
|
|
title,
|
|
pid,
|
|
process_name,
|
|
is_active,
|
|
}
|
|
}
|
|
|
|
unsafe fn get_process_name(pid: u32) -> Result<String> {
|
|
let process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid)?;
|
|
|
|
let mut buffer = vec![0u16; 1024];
|
|
let mut size = buffer.len() as u32;
|
|
|
|
QueryFullProcessImageNameW(process_handle, PROCESS_NAME_WIN32, PWSTR(buffer.as_mut_ptr()), &mut size)?;
|
|
|
|
let path = String::from_utf16_lossy(&buffer[..size as usize]);
|
|
|
|
// 提取文件名
|
|
let process_name = path.split('\\').last().unwrap_or(&path).to_string();
|
|
|
|
Ok(process_name)
|
|
}
|
|
|
|
unsafe extern "system" fn enum_windows_callback(
|
|
hwnd: HWND,
|
|
lparam: LPARAM,
|
|
) -> windows::Win32::Foundation::BOOL {
|
|
if IsWindowVisible(hwnd).as_bool() {
|
|
let len = GetWindowTextLengthW(hwnd);
|
|
if len > 0 {
|
|
let windows = &mut *(lparam.0 as *mut Vec<WindowInfo>);
|
|
windows.push(get_window_info(hwnd));
|
|
}
|
|
}
|
|
windows::Win32::Foundation::TRUE
|
|
} |