mirror of
https://github.com/kunkunsh/kunkun-ext-neohtop.git
synced 2025-04-11 17:29:45 +00:00
120 lines
3.5 KiB
Rust
120 lines
3.5 KiB
Rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
|
|
|
use sysinfo::{CpuExt, SystemExt, ProcessExt, System, PidExt, ProcessStatus};
|
|
use tauri::State;
|
|
use std::sync::Mutex;
|
|
use std::collections::HashMap;
|
|
|
|
struct AppState {
|
|
sys: Mutex<System>,
|
|
process_cache: Mutex<HashMap<u32, ProcessStaticInfo>>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct ProcessStaticInfo {
|
|
name: String,
|
|
command: String,
|
|
user: String,
|
|
}
|
|
|
|
#[derive(serde::Serialize)]
|
|
struct ProcessInfo {
|
|
pid: u32,
|
|
ppid: u32,
|
|
name: String,
|
|
cpu_usage: f32,
|
|
memory_usage: u64,
|
|
status: String,
|
|
user: String,
|
|
command: String,
|
|
threads: Option<u32>,
|
|
}
|
|
|
|
#[derive(serde::Serialize)]
|
|
struct SystemStats {
|
|
cpu_usage: Vec<f32>,
|
|
memory_total: u64,
|
|
memory_used: u64,
|
|
uptime: u64,
|
|
load_avg: [f64; 3],
|
|
}
|
|
|
|
#[tauri::command]
|
|
async fn get_processes(state: State<'_, AppState>) -> Result<(Vec<ProcessInfo>, SystemStats), String> {
|
|
let mut sys = state.sys.lock().map_err(|_| "Failed to lock system state")?;
|
|
let mut process_cache = state.process_cache.lock().map_err(|_| "Failed to lock process cache")?;
|
|
|
|
// Batch refresh system information
|
|
sys.refresh_all();
|
|
|
|
let processes = sys.processes()
|
|
.iter()
|
|
.map(|(pid, process)| {
|
|
let pid_u32 = pid.as_u32();
|
|
|
|
// Get or update cache for static process info
|
|
let static_info = process_cache.entry(pid_u32).or_insert_with(|| {
|
|
ProcessStaticInfo {
|
|
name: process.name().to_string(),
|
|
command: process.cmd().join(" "),
|
|
user: process.user_id()
|
|
.map_or_else(|| "-".to_string(), |uid| uid.to_string()),
|
|
}
|
|
});
|
|
|
|
let status = match process.status() {
|
|
ProcessStatus::Run => "Running",
|
|
ProcessStatus::Sleep => "Sleeping",
|
|
ProcessStatus::Idle => "Idle",
|
|
_ => "Unknown"
|
|
};
|
|
|
|
ProcessInfo {
|
|
pid: pid_u32,
|
|
ppid: process.parent().unwrap_or(sysinfo::Pid::from(0)).as_u32(),
|
|
name: static_info.name.clone(),
|
|
cpu_usage: process.cpu_usage(),
|
|
memory_usage: process.memory(),
|
|
status: status.to_string(),
|
|
user: static_info.user.clone(),
|
|
command: static_info.command.clone(),
|
|
threads: None,
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
let load_avg = sys.load_average();
|
|
let system_stats = SystemStats {
|
|
cpu_usage: sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(),
|
|
memory_total: sys.total_memory(),
|
|
memory_used: sys.used_memory(),
|
|
uptime: sys.uptime(),
|
|
load_avg: [load_avg.one, load_avg.five, load_avg.fifteen],
|
|
};
|
|
|
|
Ok((processes, system_stats))
|
|
}
|
|
|
|
#[tauri::command]
|
|
async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {
|
|
let sys = state.sys.lock().map_err(|_| "Failed to lock system state")?;
|
|
if let Some(process) = sys.process(sysinfo::Pid::from(pid as usize)) {
|
|
Ok(process.kill())
|
|
} else {
|
|
Ok(false)
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
tauri::Builder::default()
|
|
.manage(AppState {
|
|
sys: Mutex::new(System::new_all()),
|
|
process_cache: Mutex::new(HashMap::new()),
|
|
})
|
|
.invoke_handler(tauri::generate_handler![
|
|
get_processes,
|
|
kill_process
|
|
])
|
|
.run(tauri::generate_context!())
|
|
.expect("error while running tauri application");
|
|
} |