mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
refactor: use sysproxy-rs to set system proxy on windows (#5846)
* refactor: use sysproxy-rs to set system proxy on windows * fix: remove download sysproxy.exe task * chore: unified processing system proxy reset * docs: update Changelog.md
This commit is contained in:
@@ -23,7 +23,6 @@ use tauri_plugin_autostart::ManagerExt as _;
|
||||
pub struct Sysopt {
|
||||
update_sysproxy: AtomicBool,
|
||||
reset_sysproxy: AtomicBool,
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
inner_proxy: Arc<RwLock<(Sysproxy, Autoproxy)>>,
|
||||
guard: Arc<RwLock<GuardMonitor>>,
|
||||
}
|
||||
@@ -33,7 +32,6 @@ impl Default for Sysopt {
|
||||
Self {
|
||||
update_sysproxy: AtomicBool::new(false),
|
||||
reset_sysproxy: AtomicBool::new(false),
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
inner_proxy: Arc::new(RwLock::new((Sysproxy::default(), Autoproxy::default()))),
|
||||
guard: Arc::new(RwLock::new(GuardMonitor::new(GuardType::None, Duration::from_secs(30)))),
|
||||
}
|
||||
@@ -69,35 +67,6 @@ async fn get_bypass() -> String {
|
||||
}
|
||||
}
|
||||
|
||||
// Uses tokio Command with CREATE_NO_WINDOW flag to avoid DLL initialization issues during shutdown
|
||||
#[cfg(target_os = "windows")]
|
||||
async fn execute_sysproxy_command(args: Vec<std::string::String>) -> Result<()> {
|
||||
use crate::utils::dirs;
|
||||
use anyhow::bail;
|
||||
#[allow(unused_imports)] // Required for .creation_flags() method
|
||||
use std::os::windows::process::CommandExt as _;
|
||||
use tokio::process::Command;
|
||||
|
||||
let binary_path = dirs::service_path()?;
|
||||
let sysproxy_exe = binary_path.with_file_name("sysproxy.exe");
|
||||
|
||||
if !sysproxy_exe.exists() {
|
||||
bail!("sysproxy.exe not found");
|
||||
}
|
||||
|
||||
let output = Command::new(sysproxy_exe)
|
||||
.args(args)
|
||||
.creation_flags(0x08000000) // CREATE_NO_WINDOW - 隐藏窗口
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!("sysproxy exe run failed");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
singleton!(Sysopt, SYSOPT);
|
||||
|
||||
impl Sysopt {
|
||||
@@ -112,12 +81,12 @@ impl Sysopt {
|
||||
pub async fn refresh_guard(&self) {
|
||||
logging!(info, Type::Core, "Refreshing system proxy guard...");
|
||||
let verge = Config::verge().await.latest_arc();
|
||||
if !verge.enable_system_proxy.unwrap_or(false) {
|
||||
if !verge.enable_system_proxy.unwrap_or_default() {
|
||||
logging!(info, Type::Core, "System proxy is disabled.");
|
||||
self.access_guard().write().stop();
|
||||
return;
|
||||
}
|
||||
if !verge.enable_proxy_guard.unwrap_or(false) {
|
||||
if !verge.enable_proxy_guard.unwrap_or_default() {
|
||||
logging!(info, Type::Core, "System proxy guard is disabled.");
|
||||
return;
|
||||
}
|
||||
@@ -169,94 +138,62 @@ impl Sysopt {
|
||||
};
|
||||
let pac_port = IVerge::get_singleton_port();
|
||||
|
||||
let (sys_enable, pac_enable, proxy_host) = {
|
||||
let (sys_enable, pac_enable, proxy_host, proxy_guard) = {
|
||||
(
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.proxy_auto_config.unwrap_or(false),
|
||||
verge.enable_system_proxy.unwrap_or_default(),
|
||||
verge.proxy_auto_config.unwrap_or_default(),
|
||||
verge.proxy_host.clone().unwrap_or_else(|| String::from("127.0.0.1")),
|
||||
verge.enable_proxy_guard.unwrap_or_default(),
|
||||
)
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
// 先 await, 避免持有锁导致的 Send 问题
|
||||
let bypass = get_bypass().await;
|
||||
// 先 await, 避免持有锁导致的 Send 问题
|
||||
let bypass = get_bypass().await;
|
||||
|
||||
let (sys, auto) = &mut *self.inner_proxy.write();
|
||||
let (sys, auto) = &mut *self.inner_proxy.write();
|
||||
sys.enable = false;
|
||||
sys.host = proxy_host.clone().into();
|
||||
sys.port = port;
|
||||
sys.bypass = bypass.into();
|
||||
|
||||
auto.enable = false;
|
||||
auto.url = format!("http://{proxy_host}:{pac_port}/commands/pac");
|
||||
|
||||
self.access_guard().write().set_guard_type(GuardType::None);
|
||||
|
||||
if !sys_enable && !pac_enable {
|
||||
// disable proxy
|
||||
sys.set_system_proxy()?;
|
||||
auto.set_auto_proxy()?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if pac_enable {
|
||||
sys.enable = false;
|
||||
sys.host = proxy_host.clone().into();
|
||||
sys.port = port;
|
||||
sys.bypass = bypass.into();
|
||||
|
||||
auto.enable = false;
|
||||
auto.url = format!("http://{proxy_host}:{pac_port}/commands/pac");
|
||||
|
||||
if !sys_enable {
|
||||
sys.set_system_proxy()?;
|
||||
auto.set_auto_proxy()?;
|
||||
self.access_guard()
|
||||
.write()
|
||||
.set_guard_type(GuardType::Sysproxy(sys.clone()));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if pac_enable {
|
||||
sys.enable = false;
|
||||
auto.enable = true;
|
||||
sys.set_system_proxy()?;
|
||||
auto.set_auto_proxy()?;
|
||||
auto.enable = true;
|
||||
sys.set_system_proxy()?;
|
||||
auto.set_auto_proxy()?;
|
||||
if proxy_guard {
|
||||
self.access_guard()
|
||||
.write()
|
||||
.set_guard_type(GuardType::Autoproxy(auto.clone()));
|
||||
return Ok(());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if sys_enable {
|
||||
auto.enable = false;
|
||||
sys.enable = true;
|
||||
auto.set_auto_proxy()?;
|
||||
sys.set_system_proxy()?;
|
||||
if sys_enable {
|
||||
auto.enable = false;
|
||||
sys.enable = true;
|
||||
auto.set_auto_proxy()?;
|
||||
sys.set_system_proxy()?;
|
||||
if proxy_guard {
|
||||
self.access_guard()
|
||||
.write()
|
||||
.set_guard_type(GuardType::Sysproxy(sys.clone()));
|
||||
return Ok(());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
if !sys_enable {
|
||||
self.access_guard().write().set_guard_type(GuardType::None);
|
||||
return self.reset_sysproxy().await;
|
||||
}
|
||||
|
||||
let (args, guard_type): (Vec<std::string::String>, GuardType) = if pac_enable {
|
||||
let address = format!("http://{proxy_host}:{pac_port}/commands/pac");
|
||||
(
|
||||
vec!["pac".into(), address.clone()],
|
||||
GuardType::Autoproxy(Autoproxy {
|
||||
enable: true,
|
||||
url: address,
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
let address = format!("{proxy_host}:{port}");
|
||||
let bypass = get_bypass().await;
|
||||
let bypass_for_guard = bypass.as_str().to_owned();
|
||||
(
|
||||
vec!["global".into(), address.clone(), bypass.into()],
|
||||
GuardType::Sysproxy(Sysproxy {
|
||||
enable: true,
|
||||
host: proxy_host.clone().into(),
|
||||
port,
|
||||
bypass: bypass_for_guard,
|
||||
}),
|
||||
)
|
||||
};
|
||||
|
||||
execute_sysproxy_command(args).await?;
|
||||
self.access_guard().write().set_guard_type(guard_type);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -274,20 +211,15 @@ impl Sysopt {
|
||||
self.reset_sysproxy.store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
//直接关闭所有代理
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
let (sys, auto) = &mut *self.inner_proxy.write();
|
||||
sys.enable = false;
|
||||
sys.set_system_proxy()?;
|
||||
auto.enable = false;
|
||||
auto.set_auto_proxy()?;
|
||||
}
|
||||
// close proxy guard
|
||||
self.access_guard().write().set_guard_type(GuardType::None);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
execute_sysproxy_command(vec!["set".into(), "1".into()]).await?;
|
||||
}
|
||||
// 直接关闭所有代理
|
||||
let (sys, auto) = &mut *self.inner_proxy.write();
|
||||
sys.enable = false;
|
||||
sys.set_system_proxy()?;
|
||||
auto.enable = false;
|
||||
auto.set_auto_proxy()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -45,93 +45,25 @@ pub async fn clean_async() -> bool {
|
||||
|
||||
// 重置系统代理
|
||||
let proxy_task = tokio::task::spawn(async {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use sysproxy::{Autoproxy, Sysproxy};
|
||||
use winapi::um::winuser::{GetSystemMetrics, SM_SHUTTINGDOWN};
|
||||
|
||||
// 检查系统代理是否开启
|
||||
let sys_proxy_enabled = Config::verge().await.data_arc().enable_system_proxy.unwrap_or(false);
|
||||
|
||||
if !sys_proxy_enabled {
|
||||
logging!(info, Type::Window, "系统代理未启用,跳过重置");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否正在关机
|
||||
let is_shutting_down = unsafe { GetSystemMetrics(SM_SHUTTINGDOWN) != 0 };
|
||||
|
||||
if is_shutting_down {
|
||||
// sysproxy-rs 操作注册表(避免.exe的dll错误)
|
||||
logging!(info, Type::Window, "检测到正在关机,syspro-rs操作注册表关闭系统代理");
|
||||
|
||||
match Sysproxy::get_system_proxy() {
|
||||
Ok(mut sysproxy) => {
|
||||
sysproxy.enable = false;
|
||||
if let Err(e) = sysproxy.set_system_proxy() {
|
||||
logging!(warn, Type::Window, "Warning: 关机时关闭系统代理失败: {e}");
|
||||
} else {
|
||||
logging!(info, Type::Window, "系统代理已关闭(通过注册表)");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
logging!(warn, Type::Window, "Warning: 关机时获取代理设置失败: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭自动代理配置
|
||||
if let Ok(mut autoproxy) = Autoproxy::get_auto_proxy() {
|
||||
autoproxy.enable = false;
|
||||
let _ = autoproxy.set_auto_proxy();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 正常退出:使用 sysproxy.exe 重置代理
|
||||
logging!(info, Type::Window, "sysproxy.exe重置系统代理");
|
||||
|
||||
match timeout(Duration::from_secs(2), sysopt::Sysopt::global().reset_sysproxy()).await {
|
||||
Ok(Ok(_)) => {
|
||||
logging!(info, Type::Window, "系统代理已重置");
|
||||
true
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
logging!(warn, Type::Window, "Warning: 重置系统代理失败: {e}");
|
||||
true
|
||||
}
|
||||
Err(_) => {
|
||||
logging!(warn, Type::Window, "Warning: 重置系统代理超时,继续退出流程");
|
||||
true
|
||||
}
|
||||
}
|
||||
let sys_proxy_enabled = Config::verge().await.data_arc().enable_system_proxy.unwrap_or(false);
|
||||
if !sys_proxy_enabled {
|
||||
logging!(info, Type::Window, "系统代理未启用,跳过重置");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 非 Windows 平台:正常重置代理
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
let sys_proxy_enabled = Config::verge().await.data_arc().enable_system_proxy.unwrap_or(false);
|
||||
|
||||
if !sys_proxy_enabled {
|
||||
logging!(info, Type::Window, "系统代理未启用,跳过重置");
|
||||
return true;
|
||||
logging!(info, Type::Window, "开始重置系统代理...");
|
||||
match timeout(Duration::from_millis(1500), sysopt::Sysopt::global().reset_sysproxy()).await {
|
||||
Ok(Ok(_)) => {
|
||||
logging!(info, Type::Window, "系统代理已重置");
|
||||
true
|
||||
}
|
||||
|
||||
logging!(info, Type::Window, "开始重置系统代理...");
|
||||
|
||||
match timeout(Duration::from_millis(1500), sysopt::Sysopt::global().reset_sysproxy()).await {
|
||||
Ok(Ok(_)) => {
|
||||
logging!(info, Type::Window, "系统代理已重置");
|
||||
true
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
logging!(warn, Type::Window, "Warning: 重置系统代理失败: {e}");
|
||||
true
|
||||
}
|
||||
Err(_) => {
|
||||
logging!(warn, Type::Window, "Warning: 重置系统代理超时,继续退出");
|
||||
true
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
logging!(warn, Type::Window, "Warning: 重置系统代理失败: {e}");
|
||||
false
|
||||
}
|
||||
Err(_) => {
|
||||
logging!(warn, Type::Window, "Warning: 重置系统代理超时,继续退出");
|
||||
false
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -183,7 +115,7 @@ pub async fn clean_async() -> bool {
|
||||
Type::Window,
|
||||
"Warning: 停止core超时(可能系统正在关机),继续退出"
|
||||
);
|
||||
true
|
||||
false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user