fix: 改为跨平台管理桌面端后端进程
This commit is contained in:
@@ -1,4 +1,11 @@
|
|||||||
# 项目上下文记录
|
# 项目上下文记录
|
||||||
|
## 2026-05-21:桌面端 sidecar 进程改为跨平台管理
|
||||||
|
|
||||||
|
- Tauri 桌面端启动/关闭后端 sidecar 不再调用 Windows `netstat`、`tasklist`、`taskkill` 等控制台命令,避免启动和退出时闪过 DOS 窗口。
|
||||||
|
- 桌面端启动 sidecar 后会在应用数据目录写入 `server.pid`;下次启动前读取该 pid,并通过 `sysinfo` 跨平台确认进程名为 `capareport-server` 后再终止残留进程,pid 被复用为其他程序时不会误杀。
|
||||||
|
- 关闭桌面端时只使用 Tauri shell 的 `CommandChild.kill()` 停止当前 sidecar,并删除 `server.pid`;若 `9081` 被非本程序占用,则启动前直接报端口占用错误。
|
||||||
|
- 新增 Rust 依赖 `sysinfo`,仅启用 `system` feature;已验证 `npm run build` 和带临时 sidecar 占位文件的 `cargo check --manifest-path src-tauri\Cargo.toml` 通过,验证产物已清理。
|
||||||
|
|
||||||
## 2026-05-21:收紧系统设置页头部空间
|
## 2026-05-21:收紧系统设置页头部空间
|
||||||
|
|
||||||
- 系统设置页移除了内容卡片内重复的“系统设置/更新时间”标题栏,保留外层统一页面标题,减少首屏垂直空间占用。
|
- 系统设置页移除了内容卡片内重复的“系统设置/更新时间”标题栏,保留外层统一页面标题,减少首屏垂直空间占用。
|
||||||
|
|||||||
Generated
+96
-11
@@ -239,6 +239,7 @@ version = "3.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
"sysinfo",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-plugin-dialog",
|
"tauri-plugin-dialog",
|
||||||
@@ -1853,6 +1854,15 @@ version = "1.0.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -2018,6 +2028,16 @@ dependencies = [
|
|||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-io-kit"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-io-surface"
|
name = "objc2-io-surface"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@@ -3043,6 +3063,20 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.38.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"ntapi",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-io-kit",
|
||||||
|
"windows 0.62.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-deps"
|
name = "system-deps"
|
||||||
version = "6.2.2"
|
version = "6.2.2"
|
||||||
@@ -3090,7 +3124,7 @@ dependencies = [
|
|||||||
"tao-macros",
|
"tao-macros",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"url",
|
"url",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
@@ -3161,7 +3195,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"window-vibrancy",
|
"window-vibrancy",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3327,7 +3361,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3352,7 +3386,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4121,7 +4155,7 @@ checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"webview2-com-macros",
|
"webview2-com-macros",
|
||||||
"webview2-com-sys",
|
"webview2-com-sys",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
"windows-implement",
|
"windows-implement",
|
||||||
"windows-interface",
|
"windows-interface",
|
||||||
@@ -4145,7 +4179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c"
|
checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4201,11 +4235,23 @@ version = "0.61.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-collections",
|
"windows-collections 0.2.0",
|
||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
"windows-future",
|
"windows-future 0.2.1",
|
||||||
"windows-link 0.1.3",
|
"windows-link 0.1.3",
|
||||||
"windows-numerics",
|
"windows-numerics 0.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.62.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||||
|
dependencies = [
|
||||||
|
"windows-collections 0.3.2",
|
||||||
|
"windows-core 0.62.2",
|
||||||
|
"windows-future 0.3.2",
|
||||||
|
"windows-numerics 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4217,6 +4263,15 @@ dependencies = [
|
|||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-collections"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.62.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.61.2"
|
version = "0.61.2"
|
||||||
@@ -4251,7 +4306,18 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
"windows-link 0.1.3",
|
"windows-link 0.1.3",
|
||||||
"windows-threading",
|
"windows-threading 0.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-future"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.62.2",
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
"windows-threading 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4298,6 +4364,16 @@ dependencies = [
|
|||||||
"windows-link 0.1.3",
|
"windows-link 0.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-numerics"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.62.2",
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-result"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
@@ -4427,6 +4503,15 @@ dependencies = [
|
|||||||
"windows-link 0.1.3",
|
"windows-link 0.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-threading"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-version"
|
name = "windows-version"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@@ -4746,7 +4831,7 @@ dependencies = [
|
|||||||
"webkit2gtk",
|
"webkit2gtk",
|
||||||
"webkit2gtk-sys",
|
"webkit2gtk-sys",
|
||||||
"webview2-com",
|
"webview2-com",
|
||||||
"windows",
|
"windows 0.61.3",
|
||||||
"windows-core 0.61.2",
|
"windows-core 0.61.2",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
"x11-dl",
|
"x11-dl",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ tauri-build = { version = "2", features = [] }
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
reqwest = { version = "0.13", default-features = false, features = ["stream"] }
|
reqwest = { version = "0.13", default-features = false, features = ["stream"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
sysinfo = { version = "0.38.4", default-features = false, features = ["system"] }
|
||||||
tauri = { version = "2", features = [] }
|
tauri = { version = "2", features = [] }
|
||||||
tauri-plugin-dialog = "2"
|
tauri-plugin-dialog = "2"
|
||||||
tauri-plugin-shell = "2"
|
tauri-plugin-shell = "2"
|
||||||
|
|||||||
+63
-48
@@ -9,6 +9,7 @@ use std::sync::Mutex;
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use sysinfo::{Pid, ProcessesToUpdate, Signal, System};
|
||||||
use tauri::{Manager, Runtime};
|
use tauri::{Manager, Runtime};
|
||||||
use tauri_plugin_dialog::DialogExt;
|
use tauri_plugin_dialog::DialogExt;
|
||||||
use tauri_plugin_shell::process::CommandChild;
|
use tauri_plugin_shell::process::CommandChild;
|
||||||
@@ -17,12 +18,12 @@ use tauri_plugin_shell::ShellExt;
|
|||||||
const SERVER_PORT: u16 = 9081;
|
const SERVER_PORT: u16 = 9081;
|
||||||
const SERVER_ADDR: &str = "127.0.0.1:9081";
|
const SERVER_ADDR: &str = "127.0.0.1:9081";
|
||||||
const HTTP_ERROR_PREFIX: &str = "CAPAREPORT_HTTP_ERROR:";
|
const HTTP_ERROR_PREFIX: &str = "CAPAREPORT_HTTP_ERROR:";
|
||||||
#[cfg(target_os = "windows")]
|
const SERVER_PROCESS_NAME: &str = "capareport-server";
|
||||||
const SERVER_PROCESS_NAME: &str = "capareport-server.exe";
|
const SERVER_PID_FILE: &str = "server.pid";
|
||||||
|
|
||||||
struct ServerProcess {
|
struct ServerProcess {
|
||||||
child: CommandChild,
|
child: CommandChild,
|
||||||
pid: u32,
|
pid_file: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServerState(Mutex<Option<ServerProcess>>);
|
struct ServerState(Mutex<Option<ServerProcess>>);
|
||||||
@@ -98,7 +99,9 @@ fn start_server<R: Runtime>(app: &tauri::App<R>) -> Result<(), Box<dyn Error>> {
|
|||||||
fs::create_dir_all(data_dir.join("logs"))?;
|
fs::create_dir_all(data_dir.join("logs"))?;
|
||||||
copy_resource(app, "Configure.json", &data_dir)?;
|
copy_resource(app, "Configure.json", &data_dir)?;
|
||||||
copy_resource(app, "ReportScript.sql", &data_dir)?;
|
copy_resource(app, "ReportScript.sql", &data_dir)?;
|
||||||
stop_existing_server_on_port(SERVER_PORT);
|
let pid_file = data_dir.join(SERVER_PID_FILE);
|
||||||
|
stop_recorded_server(&pid_file);
|
||||||
|
ensure_server_port_available(SERVER_ADDR)?;
|
||||||
|
|
||||||
let port_arg = SERVER_PORT.to_string();
|
let port_arg = SERVER_PORT.to_string();
|
||||||
let (mut rx, child) = app
|
let (mut rx, child) = app
|
||||||
@@ -110,17 +113,27 @@ fn start_server<R: Runtime>(app: &tauri::App<R>) -> Result<(), Box<dyn Error>> {
|
|||||||
)
|
)
|
||||||
.args(["--host", "127.0.0.1", "--port", &port_arg])
|
.args(["--host", "127.0.0.1", "--port", &port_arg])
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
let pid = child.pid();
|
||||||
|
fs::write(&pid_file, pid.to_string())?;
|
||||||
|
|
||||||
if let Err(error) = wait_for_server(SERVER_ADDR, Duration::from_secs(60)) {
|
if let Err(error) = wait_for_server(SERVER_ADDR, Duration::from_secs(60)) {
|
||||||
let _ = child.kill();
|
let _ = child.kill();
|
||||||
|
let _ = fs::remove_file(&pid_file);
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
tauri::async_runtime::spawn(async move { while rx.recv().await.is_some() {} });
|
tauri::async_runtime::spawn(async move { while rx.recv().await.is_some() {} });
|
||||||
|
|
||||||
let pid = child.pid();
|
|
||||||
let state = app.state::<ServerState>();
|
let state = app.state::<ServerState>();
|
||||||
*state.0.lock().expect("server state lock poisoned") = Some(ServerProcess { child, pid });
|
*state.0.lock().expect("server state lock poisoned") = Some(ServerProcess { child, pid_file });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_server_port_available(addr: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
let socket_addr: SocketAddr = addr.parse()?;
|
||||||
|
if TcpStream::connect_timeout(&socket_addr, Duration::from_millis(300)).is_ok() {
|
||||||
|
return Err(format!("Port {SERVER_PORT} is already in use").into());
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,66 +159,68 @@ fn health_check(socket_addr: &SocketAddr) -> Result<bool, Box<dyn Error>> {
|
|||||||
Ok(response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200"))
|
Ok(response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
fn stop_recorded_server(pid_file: &Path) {
|
||||||
fn stop_existing_server_on_port(port: u16) {
|
let Ok(content) = fs::read_to_string(pid_file) else {
|
||||||
let Ok(output) = std::process::Command::new("netstat")
|
|
||||||
.args(["-ano", "-p", "tcp"])
|
|
||||||
.output()
|
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let marker = format!(":{port}");
|
if let Ok(pid) = content.trim().parse::<u32>() {
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
if !terminate_server_process(pid) {
|
||||||
for line in stdout.lines() {
|
let _ = fs::remove_file(pid_file);
|
||||||
if !line.contains(&marker) || !line.to_ascii_uppercase().contains("LISTENING") {
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
wait_for_process_exit(pid, Duration::from_secs(5));
|
||||||
let Some(pid) = line.split_whitespace().last() else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if pid.parse::<u32>().is_err() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if !is_capareport_server_pid(pid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = std::process::Command::new("taskkill")
|
|
||||||
.args(["/F", "/T", "/PID", pid])
|
|
||||||
.status();
|
|
||||||
}
|
}
|
||||||
|
let _ = fs::remove_file(pid_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
fn terminate_server_process(pid: u32) -> bool {
|
||||||
fn is_capareport_server_pid(pid: &str) -> bool {
|
let mut system = System::new();
|
||||||
let Ok(output) = std::process::Command::new("tasklist")
|
let pid = Pid::from_u32(pid);
|
||||||
.args(["/FI", &format!("PID eq {pid}"), "/FO", "CSV", "/NH"])
|
system.refresh_processes(ProcessesToUpdate::Some(&[pid]), true);
|
||||||
.output()
|
|
||||||
else {
|
let Some(process) = system.process(pid) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
String::from_utf8_lossy(&output.stdout)
|
if !is_server_process_name(process.name()) {
|
||||||
.to_ascii_lowercase()
|
return false;
|
||||||
.contains(SERVER_PROCESS_NAME)
|
}
|
||||||
|
|
||||||
|
if process.kill_with(Signal::Kill) != Some(true) {
|
||||||
|
let _ = process.kill();
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
fn wait_for_process_exit(pid: u32, timeout: Duration) {
|
||||||
fn stop_existing_server_on_port(_port: u16) {}
|
let started_at = Instant::now();
|
||||||
|
while started_at.elapsed() < timeout {
|
||||||
|
if !is_process_running(pid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
thread::sleep(Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_process_running(pid: u32) -> bool {
|
||||||
|
let mut system = System::new();
|
||||||
|
let pid = Pid::from_u32(pid);
|
||||||
|
system.refresh_processes(ProcessesToUpdate::Some(&[pid]), true);
|
||||||
|
system.process(pid).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_server_process_name(name: &std::ffi::OsStr) -> bool {
|
||||||
|
let normalized = name.to_string_lossy().to_ascii_lowercase();
|
||||||
|
normalized == SERVER_PROCESS_NAME || normalized == format!("{SERVER_PROCESS_NAME}.exe")
|
||||||
|
}
|
||||||
|
|
||||||
fn stop_server<R: Runtime>(app: &tauri::AppHandle<R>) {
|
fn stop_server<R: Runtime>(app: &tauri::AppHandle<R>) {
|
||||||
let state = app.state::<ServerState>();
|
let state = app.state::<ServerState>();
|
||||||
let child = state.0.lock().expect("server state lock poisoned").take();
|
let child = state.0.lock().expect("server state lock poisoned").take();
|
||||||
if let Some(process) = child {
|
if let Some(process) = child {
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
{
|
|
||||||
let _ = std::process::Command::new("taskkill")
|
|
||||||
.args(["/F", "/T", "/PID", &process.pid.to_string()])
|
|
||||||
.status();
|
|
||||||
}
|
|
||||||
let _ = process.child.kill();
|
let _ = process.child.kill();
|
||||||
|
let _ = fs::remove_file(process.pid_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user