Enriquece inventário do Windows e layout dos cards

This commit is contained in:
Esdras Renan 2025-10-13 19:42:19 -03:00
parent 26ae2aa8e5
commit 11390a9d83
2 changed files with 56 additions and 27 deletions

View file

@ -693,6 +693,7 @@ fn collect_windows_extended() -> serde_json::Value {
// Informações de build/edição e ativação // Informações de build/edição e ativação
let os_info = ps(r#" let os_info = ps(r#"
$cv = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'; $cv = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion';
$os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue;
$lsItems = Get-CimInstance -Query "SELECT Name, LicenseStatus, PartialProductKey FROM SoftwareLicensingProduct WHERE PartialProductKey IS NOT NULL" | Where-Object { $_.Name -like 'Windows*' }; $lsItems = Get-CimInstance -Query "SELECT Name, LicenseStatus, PartialProductKey FROM SoftwareLicensingProduct WHERE PartialProductKey IS NOT NULL" | Where-Object { $_.Name -like 'Windows*' };
$activatedItem = $lsItems | Where-Object { $_.LicenseStatus -eq 1 } | Select-Object -First 1; $activatedItem = $lsItems | Where-Object { $_.LicenseStatus -eq 1 } | Select-Object -First 1;
$primaryItem = if ($activatedItem) { $activatedItem } else { $lsItems | Select-Object -First 1 }; $primaryItem = if ($activatedItem) { $activatedItem } else { $lsItems | Select-Object -First 1 };
@ -704,6 +705,16 @@ fn collect_windows_extended() -> serde_json::Value {
DisplayVersion = $cv.DisplayVersion DisplayVersion = $cv.DisplayVersion
ReleaseId = $cv.ReleaseId ReleaseId = $cv.ReleaseId
EditionID = $cv.EditionID EditionID = $cv.EditionID
UBR = $cv.UBR
CompositionEditionID = $cv.CompositionEditionID
InstallationType = $cv.InstallationType
InstallDate = $cv.InstallDate
InstallationDate = $os.InstallDate
InstalledOn = $os.InstallDate
Version = $os.Version
BuildNumber = $os.BuildNumber
Caption = $os.Caption
FeatureExperiencePack = $cv.FeatureExperiencePack
LicenseStatus = $lsCode LicenseStatus = $lsCode
IsActivated = ($activatedItem -ne $null) IsActivated = ($activatedItem -ne $null)
} }

View file

@ -202,6 +202,14 @@ function readNumber(record: Record<string, unknown>, ...keys: string[]): number
return undefined return undefined
} }
function readText(record: Record<string, unknown>, ...keys: string[]): string | undefined {
const stringValue = readString(record, ...keys)
if (stringValue) return stringValue
const numberValue = readNumber(record, ...keys)
if (typeof numberValue === "number") return String(numberValue)
return undefined
}
function parseWindowsInstallDate(value: unknown): Date | null { function parseWindowsInstallDate(value: unknown): Date | null {
if (!value) return null if (!value) return null
if (value instanceof Date) return value if (value instanceof Date) return value
@ -265,6 +273,7 @@ type WindowsOsInfo = {
editionId?: string editionId?: string
displayVersion?: string displayVersion?: string
releaseId?: string releaseId?: string
version?: string
currentBuild?: string currentBuild?: string
currentBuildNumber?: string currentBuildNumber?: string
licenseStatus?: number licenseStatus?: number
@ -278,26 +287,32 @@ function parseWindowsOsInfo(raw: unknown): WindowsOsInfo | null {
const parseRecord = (value: Record<string, unknown>) => { const parseRecord = (value: Record<string, unknown>) => {
const read = (k: string, ...alts: string[]) => readString(value, k, ...alts) const read = (k: string, ...alts: string[]) => readString(value, k, ...alts)
const readNum = (...keys: string[]) => readNumber(value, ...keys) const readNum = (...keys: string[]) => readNumber(value, ...keys)
const readFlexible = (...keys: string[]) => readText(value, ...keys)
const family = read("Family")
const edition = read("Edition")
const productName = const productName =
read("ProductName", "productName", "Name", "name") ?? readFlexible("ProductName", "productName", "Name", "name", "Caption", "caption") ??
(read("Family") && read("Edition") ? `${read("Family")} ${read("Edition")}` : undefined) (family && edition ? `${family} ${edition}` : family ?? edition ?? undefined)
const editionId = const editionId =
read("EditionID", "editionId", "Edition", "edition", "SkuEdition", "skuEdition") ?? undefined readFlexible("EditionID", "editionId", "Edition", "edition", "SkuEdition", "skuEdition", "CompositionEditionID", "compositionEditionId") ??
undefined
const displayVersion = const displayVersion = readFlexible("DisplayVersion", "displayVersion")
read("DisplayVersion", "displayVersion", "Version", "version") ?? const versionValue =
read("ReleaseId", "releaseId") readFlexible("Version", "version", "ReleaseId", "releaseId") ?? displayVersion
const baseBuild = const baseBuild =
read("CurrentBuildNumber", "currentBuildNumber", "CurrentBuild", "currentBuild", "OSBuild", "osBuild") ?? readFlexible("CurrentBuildNumber", "currentBuildNumber", "CurrentBuild", "currentBuild", "OSBuild", "osBuild", "BuildNumber", "buildNumber") ??
undefined undefined
const ubr = read("UBR") ?? (readNum("UBR") ? String(readNum("UBR")) : undefined) const ubrRaw = readFlexible("UBR")
const currentBuildNumber = baseBuild ? (ubr && /^\d+$/.test(ubr) ? `${baseBuild}.${ubr}` : baseBuild) : undefined const licenseStatus = readNum("LicenseStatus", "licenseStatus")
const currentBuildNumber =
baseBuild && ubrRaw && /^\d+$/.test(ubrRaw) ? `${baseBuild}.${ubrRaw}` : baseBuild ?? readFlexible("BuildNumber", "buildNumber")
const currentBuild = baseBuild const currentBuild = baseBuild
const licenseStatus = readNum("LicenseStatus", "licenseStatus")
const isActivatedRaw = value["IsActivated"] ?? value["isActivated"] const isActivatedRaw = value["IsActivated"] ?? value["isActivated"]
const isActivated = const isActivated =
typeof isActivatedRaw === "boolean" typeof isActivatedRaw === "boolean"
@ -313,13 +328,14 @@ function parseWindowsOsInfo(raw: unknown): WindowsOsInfo | null {
parseWindowsInstallDate(value["InstalledOn"]) parseWindowsInstallDate(value["InstalledOn"])
const experience = const experience =
read("Experience", "experience", "FeatureExperiencePack", "featureExperiencePack") ?? readFlexible("Experience", "experience", "FeatureExperiencePack", "featureExperiencePack") ??
(currentBuildNumber ? `OS Build ${currentBuildNumber}` : undefined) (currentBuildNumber ? `OS Build ${currentBuildNumber}` : undefined)
return { return {
productName, productName,
editionId, editionId,
displayVersion, displayVersion,
version: versionValue,
releaseId: read("ReleaseId", "releaseId"), releaseId: read("ReleaseId", "releaseId"),
currentBuild, currentBuild,
currentBuildNumber, currentBuildNumber,
@ -845,7 +861,7 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
return [] return []
}, [windowsSoftwareRaw]) }, [windowsSoftwareRaw])
const windowsEditionLabel = windowsOsInfo?.productName ?? windowsOsInfo?.editionId ?? null const windowsEditionLabel = windowsOsInfo?.productName ?? windowsOsInfo?.editionId ?? null
const windowsVersionLabel = windowsOsInfo?.displayVersion ?? windowsOsInfo?.releaseId ?? null const windowsVersionLabel = windowsOsInfo?.displayVersion ?? windowsOsInfo?.version ?? windowsOsInfo?.releaseId ?? null
const windowsBuildLabel = windowsOsInfo?.currentBuildNumber ?? windowsOsInfo?.currentBuild ?? null const windowsBuildLabel = windowsOsInfo?.currentBuildNumber ?? windowsOsInfo?.currentBuild ?? null
const windowsInstallDateLabel = windowsOsInfo?.installDate ? formatAbsoluteDateTime(windowsOsInfo.installDate) : null const windowsInstallDateLabel = windowsOsInfo?.installDate ? formatAbsoluteDateTime(windowsOsInfo.installDate) : null
const windowsExperienceLabel = windowsOsInfo?.experience ?? null const windowsExperienceLabel = windowsOsInfo?.experience ?? null
@ -1487,12 +1503,12 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
<Card className="border-slate-200"> <Card className="border-slate-200">
<CardContent className="flex items-center gap-3 py-3"> <CardContent className="flex items-center gap-3 py-3">
<Terminal className="size-5 text-slate-500" /> <Terminal className="size-5 text-slate-500" />
<div className="min-w-0"> <div className="min-w-0 space-y-0.5">
<p className="truncate text-xs text-muted-foreground">Windows</p> <p className="text-xs text-muted-foreground">Windows</p>
<p className="truncate text-sm font-semibold text-foreground"> <p className="break-words text-sm font-semibold text-foreground">
{windowsEditionLabel ?? machine?.osName ?? "—"} {windowsEditionLabel ?? machine?.osName ?? "—"}
</p> </p>
<p className="truncate text-xs text-muted-foreground"> <p className="break-words text-xs text-muted-foreground">
{windowsVersionLabel ?? windowsBuildLabel ?? "Versão desconhecida"} {windowsVersionLabel ?? windowsBuildLabel ?? "Versão desconhecida"}
</p> </p>
</div> </div>
@ -1501,9 +1517,11 @@ export function MachineDetails({ machine }: MachineDetailsProps) {
<Card className="border-slate-200"> <Card className="border-slate-200">
<CardContent className="flex items-center gap-3 py-3"> <CardContent className="flex items-center gap-3 py-3">
<Monitor className="size-5 text-slate-500" /> <Monitor className="size-5 text-slate-500" />
<div className="min-w-0"> <div className="min-w-0 space-y-0.5">
<p className="truncate text-xs text-muted-foreground">GPU</p> <p className="text-xs text-muted-foreground">GPU</p>
<p className="truncate text-sm font-semibold text-foreground">{(windowsPrimaryGpu ?? primaryGpu)?.name ?? "—"}</p> <p className="break-words text-sm font-semibold text-foreground">
{(windowsPrimaryGpu ?? primaryGpu)?.name ?? "—"}
</p>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>