Files
TeyvatGuide/src-tauri/src/watchdog.rs
BTMuli e3f3a038f4 🎨 code fmt
2026-01-16 19:39:27 +08:00

73 lines
2.3 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.
//! 重启提权相关处理
//! @since Beta v0.9.1
#![cfg(target_os = "windows")]
use std::ptr::null_mut;
use std::time::Duration;
use tauri::AppHandle;
use widestring::U16CString;
use windows_sys::Win32::Foundation::{HANDLE, HWND};
use windows_sys::Win32::Storage::FileSystem::SYNCHRONIZE;
use windows_sys::Win32::System::Threading::{INFINITE, OpenProcess, WaitForSingleObject};
use windows_sys::Win32::UI::Shell::ShellExecuteW;
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
/// 带参数启动(使用 ShellExecuteW + runas
fn shell_runas_with_args(args: &str) -> Result<(), String> {
let exe_path = std::env::current_exe().map_err(|e| e.to_string())?;
let exe_wide =
U16CString::from_os_str(exe_path.as_os_str()).map_err(|e| format!("路径转换失败: {e}"))?;
let args_wide = U16CString::from_str(args).map_err(|e| format!("参数转换失败: {e}"))?;
let cwd_wide = exe_path
.parent()
.map(|p| U16CString::from_os_str(p.as_os_str()))
.transpose()
.map_err(|e| format!("路径转换失败: {e}"))?
.unwrap_or_else(|| U16CString::from_str("").unwrap());
let verb = U16CString::from_str("runas").unwrap();
unsafe {
let result = ShellExecuteW(
0 as HWND,
verb.as_ptr(),
exe_wide.as_ptr(),
args_wide.as_ptr(),
if cwd_wide.len() > 1 { cwd_wide.as_ptr() } else { null_mut() },
SW_SHOWNORMAL,
);
if (result as usize) > 32 { Ok(()) } else { Err("ShellExecuteW runas 启动失败".into()) }
}
}
/// 等待父进程退出(释放单例锁)后,再以管理员身份启动新实例
pub fn run_watchdog(parent_pid: u32, args_to_pass: &str) -> Result<(), String> {
let handle: HANDLE = unsafe { OpenProcess(SYNCHRONIZE, 0, parent_pid) };
if handle.is_null() {
std::thread::sleep(Duration::from_millis(300));
} else {
unsafe {
WaitForSingleObject(handle, INFINITE);
}
}
shell_runas_with_args(args_to_pass)
}
/// 以管理员权限重启应用
#[tauri::command]
pub fn run_with_admin(app_handle: AppHandle) -> Result<(), String> {
let parent_pid = std::process::id();
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
let mut cmd = std::process::Command::new(exe);
cmd
.arg("--watchdog")
.arg(format!("--ppid={}", parent_pid))
.spawn()
.map_err(|e| format!("spawn watchdog failed: {e}"))?;
app_handle.exit(0);
Ok(())
}