<# LXS - System Infos (Windows) Description: Essential system monitoring and diagnostic views. Read-only: nothing here changes the machine. Repo: https://git.hyko.cx/hykocx/lxs #> # Load LXS common library (colors, UI helpers, spinner, loggers, guards). # Prefers the sibling ..\lib\common.ps1 (repo checkout or installed layout) and # only hits the network when this script is run standalone. $LxsRawBase = if ($env:LXS_RAW_BASE) { $env:LXS_RAW_BASE } else { 'https://git.hyko.cx/hykocx/lxs/raw/branch/main' } if (-not $env:LXS_RAW_PLATFORM_BASE) { $env:LXS_RAW_PLATFORM_BASE = "$LxsRawBase/windows" } $LxsLibPath = if ($PSScriptRoot) { Join-Path $PSScriptRoot '..\lib\common.ps1' } else { $null } if ($LxsLibPath -and (Test-Path $LxsLibPath)) { . $LxsLibPath } else { try { $LxsLibSource = Invoke-RestMethod -Uri "$env:LXS_RAW_PLATFORM_BASE/lib/common.ps1" -UseBasicParsing -ErrorAction Stop } catch { Write-Error 'Failed to fetch lib/common.ps1' exit 1 } . ([scriptblock]::Create($LxsLibSource)) } $env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_system_infos.log' function Write-LxsField { param([string]$Label, $Value) Write-Host "$($script:Cyan)$($script:Bold)${Label}:$($script:NC)" foreach ($line in @($Value)) { Write-Host " $line" } Write-Host '' } function Show-LxsSystemInformation { Clear-Host Show-LxsBoxTop -Title 'SYSTEM INFORMATION' Write-Host '' try { $os = Get-CimInstance Win32_OperatingSystem $cs = Get-CimInstance Win32_ComputerSystem $cpu = @(Get-CimInstance Win32_Processor) $bios = Get-CimInstance Win32_BIOS Write-LxsField 'Operating System' "$($os.Caption) $($os.OSArchitecture)" Write-LxsField 'Version / Build' "$($os.Version) (build $($os.BuildNumber))" Write-LxsField 'Installed On' $os.InstallDate $span = (Get-Date) - $os.LastBootUpTime Write-LxsField 'System Uptime' ("{0} days, {1} hours, {2} minutes" -f $span.Days, $span.Hours, $span.Minutes) Write-LxsField 'Hostname' $env:COMPUTERNAME Write-LxsField 'Manufacturer' "$($cs.Manufacturer) $($cs.Model)" Write-LxsField 'BIOS' "$($bios.Manufacturer) $($bios.SMBIOSBIOSVersion)" Write-LxsField 'CPU' ($cpu | ForEach-Object { "$($_.Name.Trim()) ($($_.NumberOfCores)C/$($_.NumberOfLogicalProcessors)T)" }) Write-LxsField 'Memory' ("{0} GB total" -f [math]::Round($cs.TotalPhysicalMemory / 1GB, 1)) Write-LxsField 'PowerShell' $PSVersionTable.PSVersion.ToString() } catch { Write-LxsErr "Could not read system information: $($_.Exception.Message)" } try { $gpu = @(Get-CimInstance Win32_VideoController -ErrorAction Stop | ForEach-Object { "$($_.Name) (driver $($_.DriverVersion))" }) if ($gpu.Count -gt 0) { Write-LxsField 'GPU' $gpu } } catch { # Headless or restricted WMI — not worth failing the whole view. } # Activation status. LicenseStatus 1 = licensed. try { $lic = @(Get-CimInstance SoftwareLicensingProduct -ErrorAction Stop | Where-Object { $_.PartialProductKey -and $_.Name -like 'Windows*' } | Select-Object -First 1) if ($lic.Count -gt 0) { $state = switch ([int]$lic[0].LicenseStatus) { 0 { 'Unlicensed' } 1 { 'Licensed' } 2 { 'Out-of-box grace period' } 3 { 'Out-of-tolerance grace period' } 4 { 'Non-genuine grace period' } 5 { 'Notification (not activated)' } 6 { 'Extended grace' } default { 'Unknown' } } Write-LxsField 'Activation' "$state — $($lic[0].Name)" } } catch { # SoftwareLicensingProduct is unavailable on some SKUs. } } function Show-LxsDiskSpace { Clear-Host Show-LxsBoxTop -Title 'DISK SPACE' Write-Host '' Get-CimInstance Win32_LogicalDisk -Filter 'DriveType=3' | ForEach-Object { $totalGB = [math]::Round($_.Size / 1GB, 1) $freeGB = [math]::Round($_.FreeSpace / 1GB, 1) $usedGB = [math]::Round(($_.Size - $_.FreeSpace) / 1GB, 1) $pct = if ($_.Size -gt 0) { [math]::Round(100 * ($_.Size - $_.FreeSpace) / $_.Size) } else { 0 } $bar = ('#' * [math]::Round($pct / 5)).PadRight(20, '.') $color = if ($pct -ge 90) { $script:Red } else { $script:Cyan } Write-Host (" $($script:White)$($script:Bold){0,-4}$($script:NC) {1}[{2}]$($script:NC) {3,6} GB used / {4,6} GB free / {5,6} GB total ({6}%)" -f ` $_.DeviceID, $color, $bar, $usedGB, $freeGB, $totalGB, $pct) } Write-Host '' } function Show-LxsMemoryUsage { Clear-Host Show-LxsBoxTop -Title 'MEMORY USAGE' Write-Host '' $os = Get-CimInstance Win32_OperatingSystem $totalGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2) $freeGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2) $usedGB = [math]::Round($totalGB - $freeGB, 2) $pct = if ($totalGB -gt 0) { [math]::Round(100 * $usedGB / $totalGB) } else { 0 } Write-LxsField 'Physical Memory' "$usedGB GB used / $freeGB GB free / $totalGB GB total ($pct%)" $pageTotal = [math]::Round($os.SizeStoredInPagingFiles / 1MB, 2) $pageFree = [math]::Round($os.FreeSpaceInPagingFiles / 1MB, 2) Write-LxsField 'Paging File' "$([math]::Round($pageTotal - $pageFree, 2)) GB used / $pageTotal GB total" Write-Host "$($script:Cyan)$($script:Bold)Top 10 processes by memory:$($script:NC)" Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 10 | Format-Table -AutoSize @{ Name = 'PID'; Expression = { $_.Id } }, @{ Name = 'Name'; Expression = { $_.ProcessName } }, @{ Name = 'Memory (MB)'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } } | Out-String | Write-Host } function Show-LxsCpuLoad { Clear-Host Show-LxsBoxTop -Title 'CPU LOAD' Write-Host '' try { $load = (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average Write-LxsField 'Current Load' "$load%" } catch { Write-LxsWarn 'Could not read the CPU load counter.' } Write-LxsField 'Logical Processors' $env:NUMBER_OF_PROCESSORS Write-Host "$($script:Cyan)$($script:Bold)Top 10 processes by CPU time:$($script:NC)" Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 | Format-Table -AutoSize @{ Name = 'PID'; Expression = { $_.Id } }, @{ Name = 'Name'; Expression = { $_.ProcessName } }, @{ Name = 'CPU (s)'; Expression = { if ($_.CPU) { [math]::Round($_.CPU, 1) } else { 0 } } } | Out-String | Write-Host } function Show-LxsNetwork { Clear-Host Show-LxsBoxTop -Title 'NETWORK' Write-Host '' try { Get-NetIPConfiguration -ErrorAction Stop | ForEach-Object { Write-Host "$($script:Cyan)$($script:Bold)$($_.InterfaceAlias)$($script:NC) $($script:Gray)($($_.InterfaceDescription))$($script:NC)" Write-Host " IPv4 : $($_.IPv4Address.IPAddress -join ', ')" Write-Host " Gateway : $($_.IPv4DefaultGateway.NextHop -join ', ')" Write-Host " DNS : $($_.DNSServer.ServerAddresses -join ', ')" Write-Host '' } } catch { Write-LxsWarn 'Get-NetIPConfiguration unavailable; falling back to ipconfig.' ipconfig /all | Out-String | Write-Host } Write-LxsField 'Public IP' (Get-LxsPublicIP) } function Show-LxsEventLogs { Clear-Host Show-LxsBoxTop -Title 'SYSTEM LOGS' -Right 'LAST 50' Write-Host '' foreach ($logName in @('System', 'Application')) { Write-Host "$($script:Cyan)$($script:Bold)$logName — errors and warnings$($script:NC)" try { $events = Get-WinEvent -FilterHashtable @{ LogName = $logName; Level = 1, 2, 3 } -MaxEvents 25 -ErrorAction Stop $events | Format-Table -AutoSize -Wrap ` @{ Name = 'Time'; Expression = { $_.TimeCreated.ToString('MM-dd HH:mm') } }, @{ Name = 'Level'; Expression = { $_.LevelDisplayName } }, @{ Name = 'Source'; Expression = { $_.ProviderName } }, @{ Name = 'Message'; Expression = { ($_.Message -split "`n")[0] } } | Out-String -Width 160 | Write-Host } catch { Write-LxsWarn "No matching entries in $logName (or access denied)." } Write-Host '' } } function Show-LxsTopProcesses { Clear-Host Show-LxsBoxTop -Title 'TOP PROCESSES' Write-Host '' Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 20 | Format-Table -AutoSize @{ Name = 'PID'; Expression = { $_.Id } }, @{ Name = 'Name'; Expression = { $_.ProcessName } }, @{ Name = 'Memory (MB)'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } }, @{ Name = 'CPU (s)'; Expression = { if ($_.CPU) { [math]::Round($_.CPU, 1) } else { 0 } } }, @{ Name = 'Threads'; Expression = { $_.Threads.Count } } | Out-String | Write-Host } function Show-LxsDiskHealth { Clear-Host Show-LxsBoxTop -Title 'DISK HEALTH' -Right 'SMART' Write-Host '' try { $disks = @(Get-PhysicalDisk -ErrorAction Stop) } catch { Write-LxsErr 'Get-PhysicalDisk is unavailable on this system.' return } foreach ($disk in $disks) { $sizeGB = [math]::Round($disk.Size / 1GB, 1) $healthColor = if ($disk.HealthStatus -eq 'Healthy') { $script:Cyan } else { $script:Red } Write-Host "$($script:White)$($script:Bold)$($disk.FriendlyName)$($script:NC) $($script:Gray)// $($disk.MediaType), $sizeGB GB$($script:NC)" Write-Host " Health : $healthColor$($disk.HealthStatus)$($script:NC) (operational: $($disk.OperationalStatus -join ', '))" # Reliability counters need admin; report the gap instead of failing. try { $rc = $disk | Get-StorageReliabilityCounter -ErrorAction Stop if ($null -ne $rc.Temperature) { Write-Host " Temp : $($rc.Temperature) C" } if ($null -ne $rc.Wear) { Write-Host " Wear : $($rc.Wear)%" } if ($null -ne $rc.PowerOnHours) { Write-Host " Power on : $($rc.PowerOnHours) h" } if ($null -ne $rc.ReadErrorsTotal) { Write-Host " Rd errors: $($rc.ReadErrorsTotal)" } if ($null -ne $rc.WriteErrorsTotal) { Write-Host " Wr errors: $($rc.WriteErrorsTotal)" } } catch { if (-not (Test-LxsAdmin)) { Write-Host "$($script:Gray) (run as administrator for SMART counters)$($script:NC)" } else { Write-Host "$($script:Gray) (this device exposes no reliability counters)$($script:NC)" } } Write-Host '' } } function Show-LxsSystemInfoMenu { while ($true) { Clear-Host Show-LxsBoxTop -Title 'SYSTEM INFOS' Write-Host '' Show-LxsMenuItem '1' 'View system information' Show-LxsMenuItem '2' 'Check disk space' Show-LxsMenuItem '3' 'Check memory usage' Show-LxsMenuItem '4' 'Check CPU load' Show-LxsMenuItem '5' 'Check network' Show-LxsMenuItem '6' 'View system logs (errors and warnings)' Show-LxsMenuItem '7' 'Show top resource-consuming processes' Show-LxsMenuItem '8' 'Check disk health (SMART)' Show-LxsMenuItem '0' 'Back' '' -Exit Write-Host '' Show-LxsBoxBottom Write-Host '' $choice = Read-LxsChoice Write-Host '' switch ($choice) { '1' { Show-LxsSystemInformation; Read-LxsEnter } '2' { Show-LxsDiskSpace; Read-LxsEnter } '3' { Show-LxsMemoryUsage; Read-LxsEnter } '4' { Show-LxsCpuLoad; Read-LxsEnter } '5' { Show-LxsNetwork; Read-LxsEnter } '6' { Show-LxsEventLogs; Read-LxsEnter } '7' { Show-LxsTopProcesses; Read-LxsEnter } '8' { Show-LxsDiskHealth; Read-LxsEnter } '0' { return } default { Write-LxsErr 'Invalid protocol. Select 0-8.'; Start-Sleep -Seconds 1 } } } } if (-not (Assert-LxsWindows)) { exit 1 } Show-LxsSystemInfoMenu exit 75