mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
feat: add system proxy cleanup on system shutdown & prevent DLL errors
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
- Linux 打包为 `.deb` `.rpm` 提供 pkexec 依赖项
|
- Linux 打包为 `.deb` `.rpm` 提供 pkexec 依赖项
|
||||||
- 支持前端修改日志(最大文件大小、最大保留数量)
|
- 支持前端修改日志(最大文件大小、最大保留数量)
|
||||||
- 新增链式代理图形化设置功能
|
- 新增链式代理图形化设置功能
|
||||||
|
- 监听关机事件,自动关闭系统代理
|
||||||
|
|
||||||
### 🚀 优化改进
|
### 🚀 优化改进
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ async fn open_or_close_dashboard_internal() {
|
|||||||
log::info!(target: "app", "Window toggle result: {result:?}");
|
log::info!(target: "app", "Window toggle result: {result:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 异步优化的应用退出函数
|
|
||||||
pub async fn quit() {
|
pub async fn quit() {
|
||||||
logging!(debug, Type::System, true, "启动退出流程");
|
logging!(debug, Type::System, true, "启动退出流程");
|
||||||
|
|
||||||
// 获取应用句柄并设置退出标志
|
|
||||||
let Some(app_handle) = handle::Handle::global().app_handle() else {
|
let Some(app_handle) = handle::Handle::global().app_handle() else {
|
||||||
logging!(
|
logging!(
|
||||||
error,
|
error,
|
||||||
@@ -35,13 +33,11 @@ pub async fn quit() {
|
|||||||
};
|
};
|
||||||
handle::Handle::global().set_is_exiting();
|
handle::Handle::global().set_is_exiting();
|
||||||
|
|
||||||
// 优先关闭窗口,提供立即反馈
|
|
||||||
if let Some(window) = handle::Handle::global().get_window() {
|
if let Some(window) = handle::Handle::global().get_window() {
|
||||||
let _ = window.hide();
|
let _ = window.hide();
|
||||||
log::info!(target: "app", "窗口已隐藏");
|
log::info!(target: "app", "窗口已隐藏");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用异步任务处理资源清理,避免阻塞
|
|
||||||
logging!(info, Type::System, true, "开始异步清理资源");
|
logging!(info, Type::System, true, "开始异步清理资源");
|
||||||
let cleanup_result = clean_async().await;
|
let cleanup_result = clean_async().await;
|
||||||
|
|
||||||
@@ -68,12 +64,12 @@ async fn clean_async() -> bool {
|
|||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
let disable_tun = serde_json::json!({"tun": {"enable": false}});
|
let disable_tun = serde_json::json!({"tun": {"enable": false}});
|
||||||
match timeout(
|
#[cfg(target_os = "windows")]
|
||||||
Duration::from_secs(3),
|
let tun_timeout = Duration::from_secs(2);
|
||||||
IpcManager::global().patch_configs(disable_tun),
|
#[cfg(not(target_os = "windows"))]
|
||||||
)
|
let tun_timeout = Duration::from_secs(2);
|
||||||
.await
|
|
||||||
{
|
match timeout(tun_timeout, IpcManager::global().patch_configs(disable_tun)).await {
|
||||||
Ok(Ok(_)) => {
|
Ok(Ok(_)) => {
|
||||||
log::info!(target: "app", "TUN模式已禁用");
|
log::info!(target: "app", "TUN模式已禁用");
|
||||||
tokio::time::sleep(Duration::from_millis(300)).await;
|
tokio::time::sleep(Duration::from_millis(300)).await;
|
||||||
@@ -81,11 +77,12 @@ async fn clean_async() -> bool {
|
|||||||
}
|
}
|
||||||
Ok(Err(e)) => {
|
Ok(Err(e)) => {
|
||||||
log::warn!(target: "app", "禁用TUN模式失败: {e}");
|
log::warn!(target: "app", "禁用TUN模式失败: {e}");
|
||||||
false
|
// 超时不阻塞退出
|
||||||
|
true
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
log::warn!(target: "app", "禁用TUN模式超时");
|
log::warn!(target: "app", "禁用TUN模式超时(可能系统正在关机),继续退出流程");
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -94,33 +91,133 @@ async fn clean_async() -> bool {
|
|||||||
|
|
||||||
// 2. 系统代理重置
|
// 2. 系统代理重置
|
||||||
let proxy_task = async {
|
let proxy_task = async {
|
||||||
match timeout(
|
#[cfg(target_os = "windows")]
|
||||||
Duration::from_secs(3),
|
|
||||||
sysopt::Sysopt::global().reset_sysproxy(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
use sysproxy::{Autoproxy, Sysproxy};
|
||||||
log::info!(target: "app", "系统代理已重置");
|
use winapi::um::winuser::{GetSystemMetrics, SM_SHUTTINGDOWN};
|
||||||
true
|
|
||||||
|
// 检查系统代理是否开启
|
||||||
|
let sys_proxy_enabled = Config::verge()
|
||||||
|
.await
|
||||||
|
.latest_ref()
|
||||||
|
.enable_system_proxy
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !sys_proxy_enabled {
|
||||||
|
log::info!(target: "app", "系统代理未启用,跳过重置");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
Err(_) => {
|
|
||||||
log::warn!(target: "app", "重置系统代理超时");
|
// 检查是否正在关机
|
||||||
false
|
let is_shutting_down = unsafe { GetSystemMetrics(SM_SHUTTINGDOWN) != 0 };
|
||||||
|
|
||||||
|
if is_shutting_down {
|
||||||
|
// sysproxy-rs 操作注册表(避免.exe的dll错误)
|
||||||
|
log::info!(target: "app", "检测到正在关机,syspro-rs操作注册表关闭系统代理");
|
||||||
|
|
||||||
|
match Sysproxy::get_system_proxy() {
|
||||||
|
Ok(mut sysproxy) => {
|
||||||
|
sysproxy.enable = false;
|
||||||
|
if let Err(e) = sysproxy.set_system_proxy() {
|
||||||
|
log::warn!(target: "app", "关机时关闭系统代理失败: {e}");
|
||||||
|
} else {
|
||||||
|
log::info!(target: "app", "系统代理已关闭(通过注册表)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!(target: "app", "关机时获取代理设置失败: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭自动代理配置
|
||||||
|
match Autoproxy::get_auto_proxy() {
|
||||||
|
Ok(mut autoproxy) => {
|
||||||
|
autoproxy.enable = false;
|
||||||
|
let _ = autoproxy.set_auto_proxy();
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正常退出:使用 sysproxy.exe 重置代理
|
||||||
|
log::info!(target: "app", "sysproxy.exe重置系统代理");
|
||||||
|
|
||||||
|
match timeout(
|
||||||
|
Duration::from_secs(2),
|
||||||
|
sysopt::Sysopt::global().reset_sysproxy(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Ok(_)) => {
|
||||||
|
log::info!(target: "app", "系统代理已重置");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
log::warn!(target: "app", "重置系统代理失败: {e}");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
log::warn!(target: "app", "重置系统代理超时,继续退出流程");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非 Windows 平台:正常重置代理
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
let sys_proxy_enabled = Config::verge()
|
||||||
|
.await
|
||||||
|
.latest_ref()
|
||||||
|
.enable_system_proxy
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !sys_proxy_enabled {
|
||||||
|
log::info!(target: "app", "系统代理未启用,跳过重置");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!(target: "app", "开始重置系统代理...");
|
||||||
|
|
||||||
|
match timeout(
|
||||||
|
Duration::from_millis(1500),
|
||||||
|
sysopt::Sysopt::global().reset_sysproxy(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Ok(_)) => {
|
||||||
|
log::info!(target: "app", "系统代理已重置");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
log::warn!(target: "app", "重置系统代理失败: {e}");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
log::warn!(target: "app", "重置系统代理超时,继续退出");
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3. 核心服务停止
|
// 3. 核心服务停止
|
||||||
let core_task = async {
|
let core_task = async {
|
||||||
match timeout(Duration::from_secs(3), CoreManager::global().stop_core()).await {
|
#[cfg(target_os = "windows")]
|
||||||
|
let stop_timeout = Duration::from_secs(2);
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let stop_timeout = Duration::from_secs(3);
|
||||||
|
|
||||||
|
match timeout(stop_timeout, CoreManager::global().stop_core()).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
log::info!(target: "app", "核心服务已停止");
|
log::info!(target: "app", "core已停止");
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
log::warn!(target: "app", "停止核心服务超时");
|
log::warn!(target: "app", "停止core超时(可能系统正在关机),继续退出");
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -181,11 +278,15 @@ pub fn clean() -> bool {
|
|||||||
// 使用已有的异步清理函数
|
// 使用已有的异步清理函数
|
||||||
let cleanup_result = clean_async().await;
|
let cleanup_result = clean_async().await;
|
||||||
|
|
||||||
// 发送结果
|
|
||||||
let _ = tx.send(cleanup_result);
|
let _ = tx.send(cleanup_result);
|
||||||
});
|
});
|
||||||
|
|
||||||
match rx.recv_timeout(std::time::Duration::from_secs(8)) {
|
#[cfg(target_os = "windows")]
|
||||||
|
let total_timeout = std::time::Duration::from_secs(5);
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let total_timeout = std::time::Duration::from_secs(8);
|
||||||
|
|
||||||
|
match rx.recv_timeout(total_timeout) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
logging!(info, Type::System, true, "关闭操作完成,结果: {}", result);
|
logging!(info, Type::System, true, "关闭操作完成,结果: {}", result);
|
||||||
result
|
result
|
||||||
@@ -195,7 +296,7 @@ pub fn clean() -> bool {
|
|||||||
warn,
|
warn,
|
||||||
Type::System,
|
Type::System,
|
||||||
true,
|
true,
|
||||||
"清理操作超时,返回成功状态避免阻塞"
|
"清理操作超时(可能正在关机),返回成功避免阻塞"
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user