use std::process::Command;
#[derive(Debug, Clone)]
pub struct SystemInfo {
pub cores: usize,
pub memory: String,
pub serial_number: Vec<String>,
pub hardware_uuid: String,
}
impl SystemInfo {
pub fn new() -> Result<Self, String> {
let mut that = Self {
cores: 0,
memory: "".to_string(),
serial_number: vec![],
hardware_uuid: "".to_string(),
};
#[cfg(target_os = "macos")]
return match that.mac_os() {
Ok(e) => Ok(e.clone()),
Err(e) => Err(e)
};
#[cfg(target_os = "windows")]
return match that.windows() {
Ok(e) => Ok(e.clone()),
Err(e) => Err(e)
};
Err("无信息".to_string())
}
pub fn mac_os(&mut self) -> Result<&mut Self, String> {
let output = match Command::new("system_profiler")
.args(&["SPHardwareDataType"])
.output() {
Ok(e) => e,
Err(e) => {
return Err(format!("{}", e.to_string()));
}
};
let serial_number = String::from_utf8_lossy(&output.stdout);
for line in serial_number.lines() {
let text = line.trim();
if text.contains("Total Number of Cores: ") {
self.cores = text.trim_start_matches("Total Number of Cores: ").parse::<usize>().unwrap();
}
if text.contains("Memory: ") {
self.memory = text.trim_start_matches("Memory: ").to_string();
}
if text.contains("Serial Number (system): ") {
self.serial_number.push(text.trim_start_matches("Serial Number (system): ").to_string());
}
if text.contains("Hardware UUID: ") {
self.hardware_uuid = text.trim_start_matches("Hardware UUID: ").to_string();
}
}
Ok(self)
}
pub fn windows(&mut self) -> Result<&mut Self, String> {
let disk_output = match Command::new("wmic")
.args(&["diskdrive", "get", "SerialNumber"])
.output() {
Ok(e) => e,
Err(e) => {
return Err(format!("{}", e.to_string()));
}
};
let serial_number = String::from_utf8_lossy(&disk_output.stdout);
for line in serial_number.lines() {
let text = line.trim();
if !text.contains("SerialNumber") && !text.is_empty() {
self.serial_number.push(text.to_string())
}
}
let cpu_output = match Command::new("wmic")
.args(&["cpu", "get", "NumberOfCores"])
.output() {
Ok(e) => e,
Err(e) => {
return Err(format!("Failed to get CPU info: {}", e.to_string()));
}
};
let cpu_info = String::from_utf8_lossy(&cpu_output.stdout);
for line in cpu_info.lines() {
let text = line.trim();
if text.chars().all(|c| c.is_digit(10)) && !text.is_empty() {
self.cores = text.parse::<usize>().unwrap();
break
}
}
let memory_output = match Command::new("wmic")
.args(&["memorychip", "get", "capacity"])
.output() {
Ok(e) => e,
Err(e) => {
return Err(format!("Failed to get memory info: {}", e.to_string()));
}
};
let memory_info = String::from_utf8_lossy(&memory_output.stdout);
let mut total_memory: u64 = 0;
for line in memory_info.lines() {
let text = line.trim();
if text.chars().all(|c| c.is_digit(10)) && !text.is_empty() {
if let Ok(capacity) = text.parse::<u64>() {
total_memory += capacity;
}
}
}
self.memory = format!("{} GB", total_memory / 1024u64.pow(3));
let uuid_output = match Command::new("powershell")
.args(&["Get-WmiObject", "Win32_DiskDrive", "|", "Select-Object", "-ExpandProperty", "Signature"])
.output() {
Ok(e) => e,
Err(e) => {
return Err(format!("Failed to get disk UUIDs: {}", e.to_string()));
}
};
let uuid = String::from_utf8_lossy(&uuid_output.stdout);
for line in uuid.lines() {
let text = line.trim();
if !text.is_empty() {
self.hardware_uuid = text.to_string();
break
}
}
Ok(self)
}
}