From 0aa474c88e8daad910cf2c17dc9cc28476abeac8 Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Mon, 20 Oct 2025 21:52:17 -0300 Subject: [PATCH] Handle PowerShell UTF-16 output and show Windows edition --- apps/desktop/src-tauri/src/agent.rs | 46 +++++++++++++------ .../machines/admin-machines-overview.tsx | 18 +++++++- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/apps/desktop/src-tauri/src/agent.rs b/apps/desktop/src-tauri/src/agent.rs index c469b58..d3058cd 100644 --- a/apps/desktop/src-tauri/src/agent.rs +++ b/apps/desktop/src-tauri/src/agent.rs @@ -680,25 +680,45 @@ fn collect_windows_extended() -> serde_json::Value { use std::process::Command; const CREATE_NO_WINDOW: u32 = 0x08000000; + fn parse_utf16_le_bytes(bytes: &[u8]) -> Option { + if bytes.len() % 2 != 0 { + return None; + } + let utf16: Vec = bytes + .chunks_exact(2) + .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) + .collect(); + let text = String::from_utf16(&utf16).ok()?; + let trimmed = text.trim(); + if trimmed.is_empty() { + return None; + } + serde_json::from_str(trimmed).ok() + } + fn parse_powershell_json(bytes: &[u8]) -> Option { if bytes.is_empty() { return None; } if bytes.starts_with(&[0xFF, 0xFE]) { - // PowerShell usa UTF-16LE por padrĂ£o no Windows; converter para UTF-8. - let data = &bytes[2..]; - if data.len() % 2 != 0 { - return None; - } - let utf16: Vec = data - .chunks_exact(2) - .map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]])) - .collect(); - let text = String::from_utf16(&utf16).ok()?; - serde_json::from_str(&text).ok() - } else { - serde_json::from_slice(bytes).ok() + return parse_utf16_le_bytes(&bytes[2..]); } + if bytes.len() >= 2 && bytes[1] == 0 { + if let Some(val) = parse_utf16_le_bytes(bytes) { + return Some(val); + } + } + if bytes.contains(&0) { + if let Some(val) = parse_utf16_le_bytes(bytes) { + return Some(val); + } + } + let text = std::str::from_utf8(bytes).ok()?; + let trimmed = text.trim(); + if trimmed.is_empty() { + return None; + } + serde_json::from_str(trimmed).ok() } fn ps(cmd: &str) -> Option { diff --git a/src/components/admin/machines/admin-machines-overview.tsx b/src/components/admin/machines/admin-machines-overview.tsx index c55d32e..391cdac 100644 --- a/src/components/admin/machines/admin-machines-overview.tsx +++ b/src/components/admin/machines/admin-machines-overview.tsx @@ -1092,6 +1092,20 @@ export function MachineDetails({ machine }: MachineDetailsProps) { return null } })() + const osNameDisplay = useMemo(() => { + const base = machine?.osName?.trim() + const edition = windowsEditionLabel?.trim() + if (edition) { + if (base && edition.toLowerCase().includes(base.toLowerCase())) { + return edition + } + if (base) { + return `${base} ${edition}`.replace(/\s+/g, " ").trim() + } + return edition + } + return base ?? "" + }, [machine?.osName, windowsEditionLabel]) const linuxLsblk = linuxExt?.lsblk ?? [] const linuxSmartEntries = linuxExt?.smart ?? [] const normalizedHardwareGpus = Array.isArray(hardware?.gpus) @@ -1176,7 +1190,7 @@ export function MachineDetails({ machine }: MachineDetailsProps) { const summaryChips = useMemo(() => { const chips: Array<{ key: string; label: string; value: string; icon: ReactNode; tone?: "warning" | "muted" }> = [] - const osName = machine?.osName ?? "Sistema desconhecido" + const osName = osNameDisplay || "Sistema desconhecido" const osVersion = machine?.osVersion ?? windowsVersionLabel ?? "" chips.push({ key: "os", @@ -1227,7 +1241,7 @@ export function MachineDetails({ machine }: MachineDetailsProps) { }) } return chips - }, [machine?.osName, machine?.osVersion, machine?.architecture, windowsVersionLabel, windowsBuildLabel, windowsActivationStatus, primaryGpu, collaborator?.email, collaborator?.name, personaLabel]) + }, [osNameDisplay, machine?.osVersion, machine?.architecture, windowsVersionLabel, windowsBuildLabel, windowsActivationStatus, primaryGpu, collaborator?.email, collaborator?.name, personaLabel, machine?.osName]) const companyName = (() => { if (!companies || !machine?.companySlug) return machine?.companySlug ?? null