fix: 修复硬件采集过滤虚拟GPU驱动

- GPU采集过滤IddDriver/Virtual等虚拟显示驱动,优先返回真实显卡
- 磁盘采集仅选择HDD/SSD类型,排除可移动设备
- 提取powershell_lines辅助函数支持多行输出
This commit is contained in:
iven
2026-04-06 13:23:25 +08:00
parent e99ea53eba
commit 3d39f0e426

View File

@@ -53,11 +53,13 @@ fn collect_hardware(device_uid: &str) -> anyhow::Result<HardwareAsset> {
// 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<HardwareAsset> {
#[cfg(target_os = "windows")]
fn collect_system_details() -> (Option<String>, Option<String>, Option<String>) {
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<String>, Option<String>, Option<String>)
(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<String> {
fn powershell_lines(command: &str) -> Vec<String> {
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<String> {
powershell_lines(command).into_iter().next()
}
/// Collect installed software from Windows Registry via PowerShell.