mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 06:43:44 +08:00
feat: autolaunch via Startup folder on windows
This commit is contained in:
parent
c718ef3058
commit
41629df189
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#### 优化了:
|
#### 优化了:
|
||||||
- 系统代理 Bypass 设置
|
- 系统代理 Bypass 设置
|
||||||
|
- Windows 下使用 Startup 文件夹的方式实现开机自启,解决管理员模式下开机自启的各种问题
|
||||||
|
|
||||||
## v2.2.3
|
## v2.2.3
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::utils::autostart as startup_shortcut;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, IVerge},
|
config::{Config, IVerge},
|
||||||
core::handle::Handle,
|
core::handle::Handle,
|
||||||
@ -219,22 +220,68 @@ impl Sysopt {
|
|||||||
/// update the startup
|
/// update the startup
|
||||||
pub fn update_launch(&self) -> Result<()> {
|
pub fn update_launch(&self) -> Result<()> {
|
||||||
let enable_auto_launch = { Config::verge().latest().enable_auto_launch };
|
let enable_auto_launch = { Config::verge().latest().enable_auto_launch };
|
||||||
let app_handle = Handle::global().app_handle().unwrap();
|
|
||||||
let autostart_manager = app_handle.autolaunch();
|
|
||||||
|
|
||||||
let is_enable = enable_auto_launch.unwrap_or(false);
|
let is_enable = enable_auto_launch.unwrap_or(false);
|
||||||
logging!(info, true, "Setting auto-launch state to: {:?}", is_enable);
|
logging!(info, true, "Setting auto-launch state to: {:?}", is_enable);
|
||||||
if is_enable {
|
|
||||||
logging_error!(Type::System, true, "{:?}", autostart_manager.enable());
|
// 首先尝试使用快捷方式方法
|
||||||
} else {
|
#[cfg(target_os = "windows")]
|
||||||
logging_error!(Type::System, true, "{:?}", autostart_manager.disable());
|
{
|
||||||
|
if is_enable {
|
||||||
|
if let Err(e) = startup_shortcut::create_shortcut() {
|
||||||
|
log::error!(target: "app", "创建启动快捷方式失败: {}", e);
|
||||||
|
// 如果快捷方式创建失败,回退到原来的方法
|
||||||
|
self.try_original_autostart_method(is_enable);
|
||||||
|
} else {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Err(e) = startup_shortcut::remove_shortcut() {
|
||||||
|
log::error!(target: "app", "删除启动快捷方式失败: {}", e);
|
||||||
|
self.try_original_autostart_method(is_enable);
|
||||||
|
} else {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
// 非Windows平台使用原来的方法
|
||||||
|
self.try_original_autostart_method(is_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 尝试使用原来的自启动方法
|
||||||
|
fn try_original_autostart_method(&self, is_enable: bool) {
|
||||||
|
let app_handle = Handle::global().app_handle().unwrap();
|
||||||
|
let autostart_manager = app_handle.autolaunch();
|
||||||
|
|
||||||
|
if is_enable {
|
||||||
|
logging_error!(Type::System, true, "{:?}", autostart_manager.enable());
|
||||||
|
} else {
|
||||||
|
logging_error!(Type::System, true, "{:?}", autostart_manager.disable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 获取当前自启动的实际状态
|
/// 获取当前自启动的实际状态
|
||||||
pub fn get_launch_status(&self) -> Result<bool> {
|
pub fn get_launch_status(&self) -> Result<bool> {
|
||||||
|
// 首先尝试检查快捷方式是否存在
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
match startup_shortcut::is_shortcut_enabled() {
|
||||||
|
Ok(enabled) => {
|
||||||
|
log::info!(target: "app", "快捷方式自启动状态: {}", enabled);
|
||||||
|
return Ok(enabled);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(target: "app", "检查快捷方式失败,尝试原来的方法: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回退到原来的方法
|
||||||
let app_handle = Handle::global().app_handle().unwrap();
|
let app_handle = Handle::global().app_handle().unwrap();
|
||||||
let autostart_manager = app_handle.autolaunch();
|
let autostart_manager = app_handle.autolaunch();
|
||||||
|
|
||||||
|
112
src-tauri/src/utils/autostart.rs
Normal file
112
src-tauri/src/utils/autostart.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use log::info;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
/// Windows 下的开机启动文件夹路径
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn get_startup_dir() -> Result<PathBuf> {
|
||||||
|
let appdata = std::env::var("APPDATA").map_err(|_| anyhow!("无法获取 APPDATA 环境变量"))?;
|
||||||
|
|
||||||
|
let startup_dir = Path::new(&appdata)
|
||||||
|
.join("Microsoft")
|
||||||
|
.join("Windows")
|
||||||
|
.join("Start Menu")
|
||||||
|
.join("Programs")
|
||||||
|
.join("Startup");
|
||||||
|
|
||||||
|
if !startup_dir.exists() {
|
||||||
|
return Err(anyhow!("Startup 目录不存在: {:?}", startup_dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(startup_dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取当前可执行文件路径
|
||||||
|
pub fn get_exe_path() -> Result<PathBuf> {
|
||||||
|
let exe_path =
|
||||||
|
std::env::current_exe().map_err(|e| anyhow!("无法获取当前可执行文件路径: {}", e))?;
|
||||||
|
|
||||||
|
Ok(exe_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建快捷方式
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn create_shortcut() -> Result<()> {
|
||||||
|
let exe_path = get_exe_path()?;
|
||||||
|
let startup_dir = get_startup_dir()?;
|
||||||
|
let shortcut_path = startup_dir.join("Clash-Verge.lnk");
|
||||||
|
|
||||||
|
// 如果快捷方式已存在,直接返回成功
|
||||||
|
if shortcut_path.exists() {
|
||||||
|
info!(target: "app", "启动快捷方式已存在");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 PowerShell 创建快捷方式
|
||||||
|
let powershell_command = format!(
|
||||||
|
"$WshShell = New-Object -ComObject WScript.Shell; \
|
||||||
|
$Shortcut = $WshShell.CreateShortcut('{}'); \
|
||||||
|
$Shortcut.TargetPath = '{}'; \
|
||||||
|
$Shortcut.Save()",
|
||||||
|
shortcut_path.to_string_lossy().replace("\\", "\\\\"),
|
||||||
|
exe_path.to_string_lossy().replace("\\", "\\\\")
|
||||||
|
);
|
||||||
|
|
||||||
|
let output = std::process::Command::new("powershell")
|
||||||
|
.args(["-Command", &powershell_command])
|
||||||
|
.output()
|
||||||
|
.map_err(|e| anyhow!("执行 PowerShell 命令失败: {}", e))?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
let error_msg = String::from_utf8_lossy(&output.stderr);
|
||||||
|
return Err(anyhow!("创建快捷方式失败: {}", error_msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(target: "app", "成功创建启动快捷方式");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 删除快捷方式
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn remove_shortcut() -> Result<()> {
|
||||||
|
let startup_dir = get_startup_dir()?;
|
||||||
|
let shortcut_path = startup_dir.join("Clash-Verge.lnk");
|
||||||
|
|
||||||
|
// 如果快捷方式不存在,直接返回成功
|
||||||
|
if !shortcut_path.exists() {
|
||||||
|
info!(target: "app", "启动快捷方式不存在,无需删除");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除快捷方式
|
||||||
|
fs::remove_file(&shortcut_path).map_err(|e| anyhow!("删除快捷方式失败: {}", e))?;
|
||||||
|
|
||||||
|
info!(target: "app", "成功删除启动快捷方式");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查快捷方式是否存在
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn is_shortcut_enabled() -> Result<bool> {
|
||||||
|
let startup_dir = get_startup_dir()?;
|
||||||
|
let shortcut_path = startup_dir.join("Clash-Verge.lnk");
|
||||||
|
|
||||||
|
Ok(shortcut_path.exists())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非 Windows 平台使用的空方法
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
pub fn create_shortcut() -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
pub fn remove_shortcut() -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
pub fn is_shortcut_enabled() -> Result<bool> {
|
||||||
|
Ok(false)
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod autostart;
|
||||||
pub mod dirs;
|
pub mod dirs;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod help;
|
pub mod help;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user