diff --git a/Changelog.md b/Changelog.md index 02b22d82e..c39f92c43 100644 --- a/Changelog.md +++ b/Changelog.md @@ -38,6 +38,7 @@ - 修复代理组筛选后定位及滚动位置恢复异常的问题 - 修复编辑订阅配置时清空 HTTP 请求超时会报错的问题 - 修复纯 IP 连接的主机地址显示错误,并保留目标 IP 为空时的地址回退 +- 修复 Windows 管理员模式下启动 TUN 时因等待不可用 Service 导致延迟 30 秒的问题
✨ 新增功能 diff --git a/src-tauri/src/core/manager/lifecycle.rs b/src-tauri/src/core/manager/lifecycle.rs index 3d6a82cf4..5a690285f 100644 --- a/src-tauri/src/core/manager/lifecycle.rs +++ b/src-tauri/src/core/manager/lifecycle.rs @@ -9,6 +9,13 @@ use clash_verge_logging::{Type, logging}; use scopeguard::defer; use smartstring::alias::String; use tauri_plugin_clash_verge_sysinfo; +#[cfg(target_os = "windows")] +use tauri_plugin_clash_verge_sysinfo::is_current_app_handle_admin; + +#[cfg(any(target_os = "windows", test))] +const fn should_wait_for_service(tun_enabled: bool, service_ready: bool, is_admin: bool) -> bool { + tun_enabled && !service_ready && !is_admin +} /// sidecar→service 交接结果 #[cfg(target_os = "windows")] @@ -141,9 +148,18 @@ impl CoreManager { use crate::{config::Config, constants::timing, core::service}; use backon::{ConstantBuilder, Retryable as _}; - let needs_service = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false); + let tun_enabled = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false); + let service_ready = matches!(SERVICE_MANAGER.current().await, ServiceStatus::Ready); + let is_admin = is_current_app_handle_admin(Handle::app_handle()); - if !needs_service { + if !should_wait_for_service(tun_enabled, service_ready, is_admin) { + if tun_enabled && !service_ready && is_admin { + logging!( + info, + Type::Core, + "service unavailable while app is elevated; starting sidecar immediately" + ); + } return; } @@ -301,3 +317,16 @@ impl CoreManager { } } } + +#[cfg(test)] +mod tests { + use super::should_wait_for_service; + + #[test] + fn service_wait_is_only_required_for_non_admin_tun() { + assert!(should_wait_for_service(true, false, false)); + assert!(!should_wait_for_service(true, false, true)); + assert!(!should_wait_for_service(true, true, false)); + assert!(!should_wait_for_service(false, false, false)); + } +}