From bcc5ec897aa6748755ffb5321e53efb1a396b11e Mon Sep 17 00:00:00 2001
From: GyDi <zzzgydi@gmail.com>
Date: Fri, 18 Nov 2022 20:15:34 +0800
Subject: [PATCH] fix: windows issue

---
 src-tauri/src/core/core.rs        | 15 ++++++++-------
 src-tauri/src/core/win_service.rs | 14 +++++++++-----
 src-tauri/src/feat.rs             | 14 ++++++++++----
 src-tauri/src/utils/dirs.rs       | 23 +++++++++++++++--------
 4 files changed, 42 insertions(+), 24 deletions(-)

diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs
index b45ddf3..342c202 100644
--- a/src-tauri/src/core/core.rs
+++ b/src-tauri/src/core/core.rs
@@ -74,6 +74,10 @@ impl CoreManager {
     pub async fn run_core(&self) -> Result<()> {
         let config_path = Config::generate_file(ConfigType::Run)?;
 
+        if let Some(child) = self.sidecar.lock().take() {
+            let _ = child.kill();
+        }
+
         #[cfg(target_os = "windows")]
         {
             use super::win_service;
@@ -90,7 +94,7 @@ impl CoreManager {
                 // 服务模式启动失败就直接运行sidecar
                 match {
                     win_service::check_service().await?;
-                    win_service::run_core_by_service().await
+                    win_service::run_core_by_service(&config_path).await
                 } {
                     Ok(_) => return Ok(()),
                     Err(err) => {
@@ -103,12 +107,6 @@ impl CoreManager {
             }
         }
 
-        let mut sidecar = self.sidecar.lock();
-
-        if let Some(child) = sidecar.take() {
-            let _ = child.kill();
-        }
-
         let app_dir = dirs::app_home_dir()?;
         let app_dir = dirs::path_to_str(&app_dir)?;
 
@@ -137,6 +135,7 @@ impl CoreManager {
             <Result<()>>::Ok(())
         });
 
+        let mut sidecar = self.sidecar.lock();
         *sidecar = Some(cmd_child);
 
         tauri::async_runtime::spawn(async move {
@@ -193,6 +192,8 @@ impl CoreManager {
             bail!("invalid clash core name \"{clash_core}\"");
         }
 
+        log::debug!(target: "app", "change core to `{clash_core}`");
+
         Config::verge().draft().clash_core = Some(clash_core);
 
         // 清掉旧日志
diff --git a/src-tauri/src/core/win_service.rs b/src-tauri/src/core/win_service.rs
index b4ef1a1..f3f8850 100644
--- a/src-tauri/src/core/win_service.rs
+++ b/src-tauri/src/core/win_service.rs
@@ -8,6 +8,7 @@ use runas::Command as RunasCommand;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::os::windows::process::CommandExt;
+use std::path::PathBuf;
 use std::time::Duration;
 use std::{env::current_exe, process::Command as StdCommand};
 use tokio::time::sleep;
@@ -32,7 +33,7 @@ pub struct JsonResponse {
 /// Install the Clash Verge Service
 /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
 pub async fn install_service() -> Result<()> {
-    let binary_path = dirs::service_path();
+    let binary_path = dirs::service_path()?;
     let install_path = binary_path.with_file_name("install-service.exe");
 
     if !install_path.exists() {
@@ -62,7 +63,7 @@ pub async fn install_service() -> Result<()> {
 /// Uninstall the Clash Verge Service
 /// 该函数应该在协程或者线程中执行,避免UAC弹窗阻塞主线程
 pub async fn uninstall_service() -> Result<()> {
-    let binary_path = dirs::service_path();
+    let binary_path = dirs::service_path()?;
     let uninstall_path = binary_path.with_file_name("uninstall-service.exe");
 
     if !uninstall_path.exists() {
@@ -106,7 +107,7 @@ pub async fn check_service() -> Result<JsonResponse> {
 }
 
 /// start the clash by service
-pub(super) async fn run_core_by_service() -> Result<()> {
+pub(super) async fn run_core_by_service(config_file: &PathBuf) -> Result<()> {
     let status = check_service().await?;
 
     if status.code == 0 {
@@ -121,16 +122,19 @@ pub(super) async fn run_core_by_service() -> Result<()> {
     let bin_path = current_exe()?.with_file_name(clash_bin);
     let bin_path = dirs::path_to_str(&bin_path)?;
 
-    let config_dir = dirs::app_home_dir();
+    let config_dir = dirs::app_home_dir()?;
     let config_dir = dirs::path_to_str(&config_dir)?;
 
-    let log_path = dirs::service_log_file();
+    let log_path = dirs::service_log_file()?;
     let log_path = dirs::path_to_str(&log_path)?;
 
+    let config_file = dirs::path_to_str(config_file)?;
+
     let mut map = HashMap::new();
     map.insert("core_type", clash_core.as_str());
     map.insert("bin_path", bin_path);
     map.insert("config_dir", config_dir);
+    map.insert("config_file", config_file);
     map.insert("log_file", log_path);
 
     let url = format!("{SERVICE_URL}/start_clash");
diff --git a/src-tauri/src/feat.rs b/src-tauri/src/feat.rs
index 1648453..00d2ae2 100644
--- a/src-tauri/src/feat.rs
+++ b/src-tauri/src/feat.rs
@@ -42,9 +42,7 @@ pub fn change_clash_mode(mode: String) {
                     log_err!(handle::Handle::update_systray_part());
                 }
             }
-            Err(err) => {
-                log::error!(target: "app", "{err}");
-            }
+            Err(err) => log::error!(target: "app", "{err}"),
         }
     });
 }
@@ -211,9 +209,17 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
     match {
         #[cfg(target_os = "windows")]
         {
-            todo!()
+            let service_mode = patch.enable_service_mode;
+
+            if service_mode.is_some() {
+                Config::generate()?;
+                CoreManager::global().run_core().await?;
+            } else if tun_mode.is_some() {
+                update_core_config().await?;
+            }
         }
 
+        #[cfg(not(target_os = "windows"))]
         if tun_mode.is_some() {
             update_core_config().await?;
         }
diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs
index 553408a..9e99365 100644
--- a/src-tauri/src/utils/dirs.rs
+++ b/src-tauri/src/utils/dirs.rs
@@ -116,30 +116,37 @@ pub fn app_res_dir() -> Result<PathBuf> {
 }
 
 pub fn clash_pid_path() -> Result<PathBuf> {
-    unsafe { Ok(RESOURCE_DIR.clone().unwrap().join("clash.pid")) }
+    unsafe {
+        Ok(RESOURCE_DIR
+            .clone()
+            .ok_or(anyhow::anyhow!("failed to get the resource dir"))?
+            .join("clash.pid"))
+    }
 }
 
 #[cfg(windows)]
-pub fn service_path() -> PathBuf {
+pub fn service_path() -> Result<PathBuf> {
     unsafe {
-        let res_dir = RESOURCE_DIR.clone().unwrap();
-        res_dir.join("clash-verge-service.exe")
+        let res_dir = RESOURCE_DIR
+            .clone()
+            .ok_or(anyhow::anyhow!("failed to get the resource dir"))?;
+        Ok(res_dir.join("clash-verge-service.exe"))
     }
 }
 
 #[cfg(windows)]
-pub fn service_log_file() -> PathBuf {
+pub fn service_log_file() -> Result<PathBuf> {
     use chrono::Local;
 
-    let log_dir = app_logs_dir().join("service");
+    let log_dir = app_logs_dir()?.join("service");
 
     let local_time = Local::now().format("%Y-%m-%d-%H%M").to_string();
     let log_file = format!("{}.log", local_time);
     let log_file = log_dir.join(log_file);
 
-    std::fs::create_dir_all(&log_dir).unwrap();
+    let _ = std::fs::create_dir_all(&log_dir);
 
-    log_file
+    Ok(log_file)
 }
 
 pub fn path_to_str(path: &PathBuf) -> Result<&str> {
-- 
GitLab