diff --git a/scripts/check.mjs b/scripts/check.mjs index 86ac7a0..b662cdd 100644 --- a/scripts/check.mjs +++ b/scripts/check.mjs @@ -143,20 +143,26 @@ async function resolveService() { if (platform !== "win32") return; - const url = - "https://github.com/zzzgydi/clash-verge-service/releases/download/latest/clash-verge-service.exe"; - - const binName = "clash-verge-service.exe"; - const resDir = path.join(cwd, "src-tauri/resources"); - const targetPath = path.join(resDir, binName); - if (!FORCE && (await fs.pathExists(targetPath))) return; + const repo = + "https://github.com/zzzgydi/clash-verge-service/releases/download/latest"; + + async function help(bin) { + const targetPath = path.join(resDir, bin); + + if (!FORCE && (await fs.pathExists(targetPath))) return; + + const url = `${repo}/${bin}`; + await downloadFile(url, targetPath); + } await fs.mkdirp(resDir); - await downloadFile(url, targetPath); + await help("clash-verge-service.exe"); + await help("install-service.exe"); + await help("uninstall-service.exe"); - console.log(`[INFO]: resolve ${binName} finished`); + console.log(`[INFO]: resolve Service finished`); } /** diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs index 2a42c6b..bb65a19 100644 --- a/src-tauri/src/cmds.rs +++ b/src-tauri/src/cmds.rs @@ -258,20 +258,20 @@ pub mod service { #[tauri::command] pub async fn check_service() -> Result { - wrap_err!(crate::core::Service::check_service().await) + // no log + match crate::core::Service::check_service().await { + Ok(res) => Ok(res), + Err(err) => Err(err.to_string()), + } } #[tauri::command] pub async fn install_service() -> Result<(), String> { - log_if_err!(crate::core::Service::install_service().await); - let ret = wrap_err!(crate::core::Service::start_service().await); - log::info!("clash verge service started successfully"); - ret + wrap_err!(crate::core::Service::install_service().await) } #[tauri::command] pub async fn uninstall_service() -> Result<(), String> { - log_if_err!(crate::core::Service::stop_service().await); wrap_err!(crate::core::Service::uninstall_service().await) } } diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index 62b10ef..7f31390 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -191,8 +191,9 @@ pub mod win_service { use super::*; use anyhow::Context; use deelevate::{PrivilegeLevel, Token}; - use runas::Command as RunasCommond; - use std::{env::current_exe, process::Command as StdCommond}; + use runas::Command as RunasCommand; + use std::os::windows::process::CommandExt; + use std::{env::current_exe, process::Command as StdCommand}; const SERVICE_NAME: &str = "clash_verge_service"; @@ -217,61 +218,63 @@ pub mod win_service { /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 pub async fn install_service() -> Result<()> { let binary_path = dirs::service_path(); - let arg = format!("binpath={}", binary_path.as_os_str().to_string_lossy()); + let install_path = binary_path.with_file_name("install-service.exe"); + + if !install_path.exists() { + bail!("installer exe not found"); + } let token = Token::with_current_process()?; let level = token.privilege_level()?; - let args = [ - "create", - SERVICE_NAME, - arg.as_str(), - "type=own", - "start=AUTO", - "displayname=Clash Verge Service", - ]; - let status = match level { - PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?, - _ => StdCommond::new("sc").args(&args).status()?, + PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).status()?, + _ => StdCommand::new(install_path) + .creation_flags(0x08000000) + .status()?, }; - if status.success() { - return Ok(()); + if !status.success() { + bail!( + "failed to install service with status {}", + status.code().unwrap() + ); } - if status.code() == Some(1073i32) { - bail!("clash verge service is installed"); - } - - bail!( - "failed to install service with status {}", - status.code().unwrap() - ) + Ok(()) } /// Uninstall the Clash Verge Service /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 pub async fn uninstall_service() -> Result<()> { + let binary_path = dirs::service_path(); + let uninstall_path = binary_path.with_file_name("uninstall-service.exe"); + + if !uninstall_path.exists() { + bail!("uninstaller exe not found"); + } + let token = Token::with_current_process()?; let level = token.privilege_level()?; - let args = ["delete", SERVICE_NAME]; - let status = match level { - PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?, - _ => StdCommond::new("sc").args(&args).status()?, + PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).status()?, + _ => StdCommand::new(uninstall_path) + .creation_flags(0x08000000) + .status()?, }; - match status.success() { - true => Ok(()), - false => bail!( + if !status.success() { + bail!( "failed to uninstall service with status {}", status.code().unwrap() - ), + ); } + + Ok(()) } + /// [deprecated] /// start service /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程 pub async fn start_service() -> Result<()> { @@ -281,8 +284,8 @@ pub mod win_service { let args = ["start", SERVICE_NAME]; let status = match level { - PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?, - _ => StdCommond::new("sc").args(&args).status()?, + PrivilegeLevel::NotPrivileged => RunasCommand::new("sc").args(&args).status()?, + _ => StdCommand::new("sc").args(&args).status()?, }; match status.success() {