Skip to content

Commit d18b6bb

Browse files
committed
♻️ 代码重构提取
1 parent 0f107ab commit d18b6bb

3 files changed

Lines changed: 87 additions & 96 deletions

File tree

src-tauri/src/commands.rs

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -127,90 +127,3 @@ pub fn is_in_admin() -> bool {
127127
}
128128
}
129129
}
130-
131-
#[cfg(target_os = "windows")]
132-
pub fn shell_runas_with_args(args: &str) -> Result<(), String> {
133-
use std::ffi::OsStr;
134-
use std::iter::once;
135-
use std::os::windows::ffi::OsStrExt;
136-
use std::ptr::null_mut;
137-
138-
use windows_sys::Win32::Foundation::HWND;
139-
use windows_sys::Win32::UI::Shell::ShellExecuteW;
140-
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
141-
142-
fn to_wide(s: &OsStr) -> Vec<u16> {
143-
s.encode_wide().chain(once(0)).collect()
144-
}
145-
146-
let exe_path = std::env::current_exe().map_err(|e| e.to_string())?;
147-
let exe_wide = to_wide(exe_path.as_os_str());
148-
let args_wide = to_wide(OsStr::new(args));
149-
let cwd_wide =
150-
exe_path.parent().map(|p| to_wide(p.as_os_str())).unwrap_or_else(|| to_wide(OsStr::new("")));
151-
152-
unsafe {
153-
let result = ShellExecuteW(
154-
0 as HWND,
155-
to_wide(OsStr::new("runas")).as_ptr(),
156-
exe_wide.as_ptr(),
157-
args_wide.as_ptr(),
158-
if cwd_wide.len() > 1 { cwd_wide.as_ptr() } else { null_mut() },
159-
SW_SHOWNORMAL,
160-
);
161-
if (result as usize) > 32 {
162-
Ok(())
163-
} else {
164-
Err("Failed to ShellExecuteW runas".into())
165-
}
166-
}
167-
}
168-
169-
// 等待父进程退出(释放单例锁)后,再以管理员身份启动新实例
170-
#[cfg(target_os = "windows")]
171-
pub fn run_watchdog(parent_pid: u32, args_to_pass: &str) -> Result<(), String> {
172-
use std::time::Duration;
173-
use windows_sys::Win32::Foundation::HANDLE;
174-
use windows_sys::Win32::Storage::FileSystem::SYNCHRONIZE;
175-
use windows_sys::Win32::System::Threading::{OpenProcess, WaitForSingleObject, INFINITE};
176-
177-
// 打开父进程句柄用于等待
178-
let handle: HANDLE = unsafe { OpenProcess(SYNCHRONIZE, 0, parent_pid) };
179-
if handle == std::ptr::null_mut() {
180-
// 如果拿不到句柄,可能父进程已退出,稍作等待后继续
181-
std::thread::sleep(Duration::from_millis(300));
182-
} else {
183-
unsafe {
184-
WaitForSingleObject(handle, INFINITE);
185-
}
186-
}
187-
188-
// 父进程已退出 → 触发 UAC 提权启动新实例
189-
shell_runas_with_args(args_to_pass)
190-
}
191-
192-
// 以管理员权限重启应用
193-
#[tauri::command]
194-
pub fn run_with_admin(app_handle: AppHandle) -> Result<(), String> {
195-
#[cfg(not(target_os = "windows"))]
196-
{
197-
return Err("This function is only supported on Windows.".into());
198-
}
199-
200-
#[cfg(target_os = "windows")]
201-
{
202-
let parent_pid = std::process::id();
203-
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
204-
let mut cmd = std::process::Command::new(exe);
205-
cmd
206-
.arg("--watchdog")
207-
.arg(format!("--ppid={}", parent_pid))
208-
// 看门狗不加载单例插件(通过参数决定 main 的初始化)
209-
.spawn()
210-
.map_err(|e| format!("spawn watchdog failed: {e}"))?;
211-
212-
// 立即退出:单例锁释放
213-
app_handle.exit(0);
214-
Ok(())
215-
}
216-
}

src-tauri/src/lib.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ mod commands;
66
mod plugins;
77
mod utils;
88
#[cfg(target_os = "windows")]
9+
mod watchdog;
10+
#[cfg(target_os = "windows")]
911
mod yae;
1012

1113
use crate::client::create_mhy_client;
12-
use crate::commands::{
13-
create_window, execute_js, get_dir_size, init_app, is_in_admin, run_watchdog, run_with_admin,
14-
};
14+
use crate::commands::{create_window, execute_js, get_dir_size, init_app, is_in_admin};
1515
use crate::plugins::{build_log_plugin, build_si_plugin};
16-
#[cfg(target_os = "windows")]
17-
use crate::yae::call_yae_dll;
1816
use tauri::{generate_context, generate_handler, Manager, Window, WindowEvent};
1917

2018
// 窗口事件处理
@@ -56,7 +54,7 @@ pub fn run() {
5654
}
5755
}
5856
// 等父进程退出后再 runas 启动管理员实例,传入 --elevated 标志
59-
let _ = run_watchdog(ppid, "--elevated");
57+
let _ = watchdog::run_watchdog(ppid, "--elevated");
6058
// 看门狗退出
6159
return;
6260
}
@@ -93,10 +91,11 @@ pub fn run() {
9391
execute_js,
9492
get_dir_size,
9593
create_mhy_client,
96-
#[cfg(target_os = "windows")]
97-
call_yae_dll,
9894
is_in_admin,
99-
run_with_admin
95+
#[cfg(target_os = "windows")]
96+
yae::call_yae_dll,
97+
#[cfg(target_os = "windows")]
98+
watchdog::run_with_admin
10099
])
101100
.run(generate_context!())
102101
.expect("error while running tauri application");

src-tauri/src/watchdog.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//! 重启提权相关处理
2+
//! @since Beta v0.8.7
3+
#![cfg(target_os = "windows")]
4+
5+
use std::ffi::OsStr;
6+
use std::iter::once;
7+
use std::os::windows::ffi::OsStrExt;
8+
use std::ptr::null_mut;
9+
use std::time::Duration;
10+
use tauri::AppHandle;
11+
use windows_sys::Win32::Foundation::{HANDLE, HWND};
12+
use windows_sys::Win32::Storage::FileSystem::SYNCHRONIZE;
13+
use windows_sys::Win32::System::Threading::{OpenProcess, WaitForSingleObject, INFINITE};
14+
use windows_sys::Win32::UI::Shell::ShellExecuteW;
15+
use windows_sys::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
16+
17+
// 带参数启动
18+
fn shell_runas_with_args(args: &str) -> Result<(), String> {
19+
fn to_wide(s: &OsStr) -> Vec<u16> {
20+
s.encode_wide().chain(once(0)).collect()
21+
}
22+
23+
let exe_path = std::env::current_exe().map_err(|e| e.to_string())?;
24+
let exe_wide = to_wide(exe_path.as_os_str());
25+
let args_wide = to_wide(OsStr::new(args));
26+
let cwd_wide =
27+
exe_path.parent().map(|p| to_wide(p.as_os_str())).unwrap_or_else(|| to_wide(OsStr::new("")));
28+
29+
unsafe {
30+
let result = ShellExecuteW(
31+
0 as HWND,
32+
to_wide(OsStr::new("runas")).as_ptr(),
33+
exe_wide.as_ptr(),
34+
args_wide.as_ptr(),
35+
if cwd_wide.len() > 1 { cwd_wide.as_ptr() } else { null_mut() },
36+
SW_SHOWNORMAL,
37+
);
38+
if (result as usize) > 32 {
39+
Ok(())
40+
} else {
41+
Err("Failed to ShellExecuteW runas".into())
42+
}
43+
}
44+
}
45+
46+
// 等待父进程退出(释放单例锁)后,再以管理员身份启动新实例
47+
pub fn run_watchdog(parent_pid: u32, args_to_pass: &str) -> Result<(), String> {
48+
// 打开父进程句柄用于等待
49+
let handle: HANDLE = unsafe { OpenProcess(SYNCHRONIZE, 0, parent_pid) };
50+
if handle == std::ptr::null_mut() {
51+
// 如果拿不到句柄,可能父进程已退出,稍作等待后继续
52+
std::thread::sleep(Duration::from_millis(300));
53+
} else {
54+
unsafe {
55+
WaitForSingleObject(handle, INFINITE);
56+
}
57+
}
58+
59+
// 父进程已退出 → 触发 UAC 提权启动新实例
60+
shell_runas_with_args(args_to_pass)
61+
}
62+
63+
// 以管理员权限重启应用
64+
#[tauri::command]
65+
pub fn run_with_admin(app_handle: AppHandle) -> Result<(), String> {
66+
let parent_pid = std::process::id();
67+
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
68+
let mut cmd = std::process::Command::new(exe);
69+
cmd
70+
.arg("--watchdog")
71+
.arg(format!("--ppid={}", parent_pid))
72+
// 看门狗不加载单例插件(通过参数决定 main 的初始化)
73+
.spawn()
74+
.map_err(|e| format!("spawn watchdog failed: {e}"))?;
75+
76+
// 立即退出:单例锁释放
77+
app_handle.exit(0);
78+
Ok(())
79+
}

0 commit comments

Comments
 (0)