Files
work-secretfile-selfcheck/src/inspect/external.rs
xiaji 7e256c426f feat(ui): 安全软件风格主题 + 三阶段进度/日志 + XLSX 支持
- 主面板:阶段1扫描全盘 → 阶段2抽样 → 阶段3抽检,每阶段独立进度条/已用时/分类型 chips

- 日志:按类型着色(命中红/未命中绿/警告黄/阶段青)

- 主题:暗绿底 + 鲜绿/青色强调,圆角胶囊按钮(material::security_dark)

- 抽检:SampleMode 枚举支持按份数/百分比/全部;设置页 C 组动态切换

- 抽检:XLSX 检查器(zip + quick-xml 解析 sharedStrings 与 sheet)

- 扫描:walker 进度回调(已访问、命中候选、当前目录)

- 兼容:quick-xml 0.36 使用 reader.config_mut().trim_text()

- 仓库:新增 .gitignore 忽略 venv/pyc/target/构建产物
2026-06-10 12:20:25 +08:00

95 lines
2.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 进程管理:启进程、关闭窗口、强杀
use std::path::Path;
use windows_sys::Win32::Foundation::HWND;
use windows_sys::Win32::System::Threading::{
OpenProcess, TerminateProcess, WaitForSingleObject, PROCESS_TERMINATE, PROCESS_VM_READ,
};
use windows_sys::Win32::UI::WindowsAndMessaging::{
EnumWindows, GetWindowThreadProcessId, PostMessageW, WM_CLOSE,
};
use std::cell::RefCell;
thread_local! {
static ENUM_RESULT: RefCell<EnumResult> = RefCell::new(EnumResult { hwnd: std::ptr::null_mut(), pid: 0 });
}
struct EnumResult { hwnd: HWND, pid: u32 }
unsafe extern "system" fn enum_callback(hwnd: HWND, _lparam: isize) -> i32 {
let mut proc_id: u32 = 0;
GetWindowThreadProcessId(hwnd, &mut proc_id);
ENUM_RESULT.with(|r| {
*r.borrow_mut() = EnumResult { hwnd, pid: proc_id };
});
1 // continue
}
/// 启动的子进程
pub struct Child {
pub pid: u32,
pub _handle: Option<std::process::Child>,
}
unsafe impl Send for Child {}
unsafe impl Sync for Child {}
/// 启动外部进程
pub fn spawn(exe: &Path, args: &str) -> anyhow::Result<Child> {
let mut cmd = std::process::Command::new(exe);
for arg in args.split_whitespace() {
cmd.arg(arg.trim_matches('"'));
}
let child = cmd.spawn().map_err(|e| anyhow::anyhow!("启动 {:?} 失败:{}", exe, e))?;
Ok(Child { pid: child.id(), _handle: Some(child) })
}
/// 通过 PID 找到主窗口 HWND
pub fn find_hwnd_by_pid(pid: u32) -> Option<HWND> {
unsafe {
let _ = EnumWindows(Some(enum_callback), 0);
}
let r = ENUM_RESULT.with(|r| r.borrow().hwnd);
let p = ENUM_RESULT.with(|r| r.borrow().pid);
if p == pid && !r.is_null() { Some(r) } else { None }
}
/// 优雅关闭PostMessage WM_CLOSE 给主窗口 → 等待 → taskkill
pub fn close(child: &Child, cfg: &crate::config::ViewerSettings) -> anyhow::Result<()> {
if let Some(hwnd) = find_hwnd_by_pid(child.pid) {
unsafe {
PostMessageW(hwnd, WM_CLOSE, 0, 0);
}
std::thread::sleep(std::time::Duration::from_millis(cfg.close_wait_ms));
}
if is_running(child.pid) {
kill(child.pid);
}
Ok(())
}
/// 进程是否仍在运行
pub fn is_running(pid: u32) -> bool {
unsafe {
let h = OpenProcess(PROCESS_VM_READ, 0, pid);
if h.is_null() { return false; }
let r = WaitForSingleObject(h, 0);
windows_sys::Win32::Foundation::CloseHandle(h);
r != 0
}
}
/// 强杀
pub fn kill(pid: u32) {
unsafe {
let h = OpenProcess(PROCESS_TERMINATE, 0, pid);
if !h.is_null() {
TerminateProcess(h, 1);
windows_sys::Win32::Foundation::CloseHandle(h);
}
let _ = std::process::Command::new("taskkill")
.arg("/F").arg("/PID").arg(pid.to_string()).arg("/T")
.output();
}
}