fix: change service installer and uninstaller
This commit is contained in:
parent
77ef3847ce
commit
f88989bd4b
@ -143,20 +143,26 @@ async function resolveService() {
|
|||||||
|
|
||||||
if (platform !== "win32") return;
|
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 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 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`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,20 +258,20 @@ pub mod service {
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn check_service() -> Result<JsonResponse, String> {
|
pub async fn check_service() -> Result<JsonResponse, String> {
|
||||||
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]
|
#[tauri::command]
|
||||||
pub async fn install_service() -> Result<(), String> {
|
pub async fn install_service() -> Result<(), String> {
|
||||||
log_if_err!(crate::core::Service::install_service().await);
|
wrap_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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn uninstall_service() -> Result<(), String> {
|
pub async fn uninstall_service() -> Result<(), String> {
|
||||||
log_if_err!(crate::core::Service::stop_service().await);
|
|
||||||
wrap_err!(crate::core::Service::uninstall_service().await)
|
wrap_err!(crate::core::Service::uninstall_service().await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,8 +191,9 @@ pub mod win_service {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use deelevate::{PrivilegeLevel, Token};
|
use deelevate::{PrivilegeLevel, Token};
|
||||||
use runas::Command as RunasCommond;
|
use runas::Command as RunasCommand;
|
||||||
use std::{env::current_exe, process::Command as StdCommond};
|
use std::os::windows::process::CommandExt;
|
||||||
|
use std::{env::current_exe, process::Command as StdCommand};
|
||||||
|
|
||||||
const SERVICE_NAME: &str = "clash_verge_service";
|
const SERVICE_NAME: &str = "clash_verge_service";
|
||||||
|
|
||||||
@ -217,61 +218,63 @@ pub mod win_service {
|
|||||||
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
||||||
pub async fn install_service() -> Result<()> {
|
pub async fn install_service() -> Result<()> {
|
||||||
let binary_path = dirs::service_path();
|
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 token = Token::with_current_process()?;
|
||||||
let level = token.privilege_level()?;
|
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 {
|
let status = match level {
|
||||||
PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?,
|
PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).status()?,
|
||||||
_ => StdCommond::new("sc").args(&args).status()?,
|
_ => StdCommand::new(install_path)
|
||||||
|
.creation_flags(0x08000000)
|
||||||
|
.status()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
if status.success() {
|
if !status.success() {
|
||||||
return Ok(());
|
bail!(
|
||||||
|
"failed to install service with status {}",
|
||||||
|
status.code().unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.code() == Some(1073i32) {
|
Ok(())
|
||||||
bail!("clash verge service is installed");
|
|
||||||
}
|
|
||||||
|
|
||||||
bail!(
|
|
||||||
"failed to install service with status {}",
|
|
||||||
status.code().unwrap()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uninstall the Clash Verge Service
|
/// Uninstall the Clash Verge Service
|
||||||
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
||||||
pub async fn uninstall_service() -> Result<()> {
|
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 token = Token::with_current_process()?;
|
||||||
let level = token.privilege_level()?;
|
let level = token.privilege_level()?;
|
||||||
|
|
||||||
let args = ["delete", SERVICE_NAME];
|
|
||||||
|
|
||||||
let status = match level {
|
let status = match level {
|
||||||
PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?,
|
PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).status()?,
|
||||||
_ => StdCommond::new("sc").args(&args).status()?,
|
_ => StdCommand::new(uninstall_path)
|
||||||
|
.creation_flags(0x08000000)
|
||||||
|
.status()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
match status.success() {
|
if !status.success() {
|
||||||
true => Ok(()),
|
bail!(
|
||||||
false => bail!(
|
|
||||||
"failed to uninstall service with status {}",
|
"failed to uninstall service with status {}",
|
||||||
status.code().unwrap()
|
status.code().unwrap()
|
||||||
),
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [deprecated]
|
||||||
/// start service
|
/// start service
|
||||||
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
/// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
|
||||||
pub async fn start_service() -> Result<()> {
|
pub async fn start_service() -> Result<()> {
|
||||||
@ -281,8 +284,8 @@ pub mod win_service {
|
|||||||
let args = ["start", SERVICE_NAME];
|
let args = ["start", SERVICE_NAME];
|
||||||
|
|
||||||
let status = match level {
|
let status = match level {
|
||||||
PrivilegeLevel::NotPrivileged => RunasCommond::new("sc").args(&args).status()?,
|
PrivilegeLevel::NotPrivileged => RunasCommand::new("sc").args(&args).status()?,
|
||||||
_ => StdCommond::new("sc").args(&args).status()?,
|
_ => StdCommand::new("sc").args(&args).status()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
match status.success() {
|
match status.success() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user