diff --git a/crates/client/src/asset/mod.rs b/crates/client/src/asset/mod.rs index 4927262..f41e230 100644 --- a/crates/client/src/asset/mod.rs +++ b/crates/client/src/asset/mod.rs @@ -53,11 +53,13 @@ fn collect_hardware(device_uid: &str) -> anyhow::Result { // Disk — pick the largest non-removable disk let disks = sysinfo::Disks::new_with_refreshed_list(); let (disk_model, disk_total_mb) = disks.iter() + .filter(|d| d.kind() == sysinfo::DiskKind::HDD || d.kind() == sysinfo::DiskKind::SSD) .max_by_key(|d| d.total_space()) .map(|d| { - let name = d.name().to_string_lossy().to_string(); let total = d.total_space() / 1024 / 1024; - (if name.is_empty() { "Unknown".to_string() } else { name }, total) + let name = d.name().to_string_lossy().to_string(); + let model = if name.is_empty() { "Unknown".to_string() } else { name }; + (model, total) }) .unwrap_or_else(|| ("Unknown".to_string(), 0)); @@ -79,7 +81,14 @@ fn collect_hardware(device_uid: &str) -> anyhow::Result { #[cfg(target_os = "windows")] fn collect_system_details() -> (Option, Option, Option) { - let gpu = powershell_first("Get-CimInstance Win32_VideoController | Select-Object -ExpandProperty Caption"); + // GPU: query all controllers, filter out virtual/IDDDriver devices, prefer real GPU + let gpu = { + let gpus = powershell_lines( + "Get-CimInstance Win32_VideoController | Where-Object { $_.Name -notmatch 'IddDriver|Virtual|Basic Render|Microsoft Basic Display|Remote Desktop|Mirror Driver' } | Select-Object -ExpandProperty Name" + ); + // Prefer NVIDIA/AMD/Intel, fallback to first non-virtual + gpus.into_iter().next() + }; let mb_manufacturer = powershell_first("Get-CimInstance Win32_BaseBoard | Select-Object -ExpandProperty Manufacturer"); let mb_product = powershell_first("Get-CimInstance Win32_BaseBoard | Select-Object -ExpandProperty Product"); let motherboard = match (mb_manufacturer, mb_product) { @@ -98,19 +107,29 @@ fn collect_system_details() -> (Option, Option, Option) (None, None, None) } -/// Run a PowerShell command and return the first non-empty line of output. +/// Run a PowerShell command and return all non-empty lines of output. #[cfg(target_os = "windows")] -fn powershell_first(command: &str) -> Option { +fn powershell_lines(command: &str) -> Vec { use std::process::Command; - let output = Command::new("powershell") + let output = match Command::new("powershell") .args(["-NoProfile", "-NonInteractive", "-Command", &format!("[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; {}", command)]) .output() - .ok()?; - let stdout = String::from_utf8_lossy(&output.stdout); - stdout.lines() + { + Ok(o) => o, + Err(_) => return Vec::new(), + }; + String::from_utf8_lossy(&output.stdout) + .lines() .map(|l| l.trim().to_string()) - .find(|l| !l.is_empty()) + .filter(|l| !l.is_empty()) + .collect() +} + +/// Run a PowerShell command and return the first non-empty line of output. +#[cfg(target_os = "windows")] +fn powershell_first(command: &str) -> Option { + powershell_lines(command).into_iter().next() } /// Collect installed software from Windows Registry via PowerShell.