Private/Get-WUSystemInfo.ps1
function Get-WUSystemInfo { <# .SYNOPSIS Gathers comprehensive system information for Windows Update diagnostics. .DESCRIPTION Collects system information relevant to Windows Update operations including OS version, hardware details, disk space, and configuration details. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $sysInfo = Get-WUSystemInfo -LogPath "C:\Logs\wu.log" .NOTES This is a private function used internally by the WindowsUpdateTools module. Returns a PSCustomObject with comprehensive system information. #> [CmdletBinding()] param( [string]$LogPath ) Write-WULog -Message "Collecting comprehensive system information" -LogPath $LogPath try { # Get basic OS information $os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop $computer = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop $bios = Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop # Get disk information for system drive $systemDrive = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DeviceID -eq $env:SystemDrive } # Calculate disk space metrics $totalSpaceGB = [math]::Round($systemDrive.Size / 1GB, 2) $freeSpaceGB = [math]::Round($systemDrive.FreeSpace / 1GB, 2) $usedSpaceGB = $totalSpaceGB - $freeSpaceGB $freeSpacePercent = [math]::Round(($freeSpaceGB / $totalSpaceGB) * 100, 1) # Get network adapter information (for connectivity analysis) $networkAdapters = Get-CimInstance -ClassName Win32_NetworkAdapter | Where-Object { $_.NetConnectionStatus -eq 2 } | # Connected adapters only Select-Object Name, MACAddress, Speed # Get Windows Update related registry information $osVersion = [System.Environment]::OSVersion.Version $buildNumber = $os.BuildNumber $releaseId = $null $ubr = $null # Update Build Revision try { # Get release ID and UBR from registry $versionInfo = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -ErrorAction SilentlyContinue if ($versionInfo) { $releaseId = $versionInfo.ReleaseId $ubr = $versionInfo.UBR } } catch { Write-WULog -Message "Could not retrieve version details from registry" -Level Warning -LogPath $LogPath } # Check for Windows Update for Business settings $wufbConfigured = $false try { $wufbKeys = @( "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate", "HKLM:\SOFTWARE\Microsoft\PolicyManager\current\device\Update" ) foreach ($key in $wufbKeys) { if (Test-Path $key) { $wufbConfigured = $true break } } } catch { Write-WULog -Message "Could not check Windows Update for Business configuration" -Level Warning -LogPath $LogPath } # Check for domain membership $domainInfo = "Workgroup" try { if ($computer.PartOfDomain) { $domainInfo = $computer.Domain } } catch { Write-WULog -Message "Could not determine domain membership" -Level Warning -LogPath $LogPath } # Check system uptime $uptime = (Get-Date) - $os.LastBootUpTime # Check for pending reboot $pendingReboot = Test-WUPendingReboot # Determine Windows edition and licensing status $windowsEdition = $os.Caption $licensingStatus = "Unknown" try { $licensingInfo = Get-CimInstance -ClassName SoftwareLicensingProduct | Where-Object { $_.PartialProductKey -and $_.Name -like "*Windows*" } | Select-Object -First 1 if ($licensingInfo) { $licensingStatus = switch ($licensingInfo.LicenseStatus) { 0 { "Unlicensed" } 1 { "Licensed" } 2 { "OOBGrace" } 3 { "OOTGrace" } 4 { "NonGenuineGrace" } 5 { "Notification" } 6 { "ExtendedGrace" } default { "Unknown" } } } } catch { Write-WULog -Message "Could not determine licensing status" -Level Warning -LogPath $LogPath } # Create comprehensive system info object $systemInfo = [PSCustomObject]@{ # Basic system information ComputerName = $computer.Name Manufacturer = $computer.Manufacturer Model = $computer.Model SerialNumber = $bios.SerialNumber BiosVersion = $bios.SMBIOSBIOSVersion # Operating system details OperatingSystem = $windowsEdition OSVersion = $osVersion.ToString() BuildNumber = $buildNumber ReleaseId = $releaseId UpdateBuildRevision = $ubr Architecture = $os.OSArchitecture InstallDate = $os.InstallDate LicensingStatus = $licensingStatus # Hardware information TotalRAM_GB = [math]::Round($computer.TotalPhysicalMemory / 1GB, 2) ProcessorCount = $computer.NumberOfLogicalProcessors ProcessorArchitecture = $computer.SystemType # Disk space information SystemDrive = $env:SystemDrive TotalSpace_GB = $totalSpaceGB FreeSpace_GB = $freeSpaceGB UsedSpace_GB = $usedSpaceGB FreeSpacePercent = $freeSpacePercent LowDiskSpace = $freeSpaceGB -lt 10 # Flag if less than 10GB free CriticalDiskSpace = $freeSpaceGB -lt 5 # Flag if less than 5GB free # Network and connectivity NetworkAdapters = $networkAdapters ConnectedAdapterCount = $networkAdapters.Count # System state LastBootTime = $os.LastBootUpTime Uptime_Hours = [math]::Round($uptime.TotalHours, 1) PendingReboot = $pendingReboot # Domain and management DomainMembership = $domainInfo PartOfDomain = $computer.PartOfDomain WUfBConfigured = $wufbConfigured # Time and locale TimeZone = (Get-TimeZone).Id CurrentTime = Get-Date # Additional system flags IsVirtualMachine = Test-WUVirtualMachine IsServerOS = $os.ProductType -ne 1 # 1 = Workstation, 2 = Domain Controller, 3 = Server # .NET Framework version (important for SetupDiag) DotNetVersion = Get-WUDotNetVersion } # Log key information Write-WULog -Message "System: $($systemInfo.Manufacturer) $($systemInfo.Model)" -LogPath $LogPath Write-WULog -Message "OS: $($systemInfo.OperatingSystem) Build $($systemInfo.BuildNumber)" -LogPath $LogPath Write-WULog -Message "RAM: $($systemInfo.TotalRAM_GB) GB, Disk Free: $($systemInfo.FreeSpace_GB) GB ($($systemInfo.FreeSpacePercent)%)" -LogPath $LogPath Write-WULog -Message "Uptime: $($systemInfo.Uptime_Hours) hours, Domain: $($systemInfo.DomainMembership)" -LogPath $LogPath if ($systemInfo.LowDiskSpace) { Write-WULog -Message "Low disk space detected ($($systemInfo.FreeSpace_GB) GB free)" -Level Warning -LogPath $LogPath } if ($systemInfo.PendingReboot) { Write-WULog -Message "Pending reboot detected" -Level Warning -LogPath $LogPath } return $systemInfo } catch { Write-WULog -Message "Error collecting system information: $($_.Exception.Message)" -Level Error -LogPath $LogPath # Return minimal system info object on error return [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME OperatingSystem = "Unknown" OSVersion = "Unknown" BuildNumber = "Unknown" Architecture = "Unknown" TotalRAM_GB = 0 FreeSpace_GB = 0 LastBootTime = $null ErrorOccurred = $true ErrorMessage = $_.Exception.Message } } } function Test-WUPendingReboot { <# .SYNOPSIS Checks if the system has a pending reboot. .DESCRIPTION Checks various registry locations and system state to determine if a reboot is pending. #> try { # Check multiple indicators of pending reboot $pendingReboot = $false # Windows Update pending reboot if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired") { $pendingReboot = $true } # Component Based Servicing pending reboot if (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending") { $pendingReboot = $true } # Pending file rename operations $pendingFileRenames = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "PendingFileRenameOperations" -ErrorAction SilentlyContinue if ($pendingFileRenames) { $pendingReboot = $true } # System Center Configuration Manager pending reboot if (Test-Path "HKLM:\SOFTWARE\Microsoft\SMS\Mobile Client\Reboot Management\RebootData") { $pendingReboot = $true } return $pendingReboot } catch { return $false } } function Test-WUVirtualMachine { <# .SYNOPSIS Detects if the system is running in a virtual machine. .DESCRIPTION Checks various system indicators to determine if running in a VM environment. #> try { # Check common VM indicators $computer = Get-CimInstance -ClassName Win32_ComputerSystem $bios = Get-CimInstance -ClassName Win32_BIOS # Common VM manufacturers and models $vmIndicators = @( "Microsoft Corporation", # Hyper-V "VMware", # VMware "VirtualBox", # VirtualBox "Xen", # Xen "QEMU", # QEMU "Parallels", # Parallels "Red Hat", # KVM/RHEV "oVirt" # oVirt ) foreach ($indicator in $vmIndicators) { if ($computer.Manufacturer -like "*$indicator*" -or $computer.Model -like "*$indicator*" -or $bios.Manufacturer -like "*$indicator*") { return $true } } # Check for VM-specific hardware if ($computer.Model -like "*Virtual*" -or $computer.Model -like "*VMware*" -or $computer.Model -like "*VirtualBox*") { return $true } return $false } catch { return $false } } function Get-WUDotNetVersion { <# .SYNOPSIS Gets the installed .NET Framework version. .DESCRIPTION Determines the highest .NET Framework version installed on the system. #> try { $netVersions = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP" -Recurse -ErrorAction SilentlyContinue | Get-ItemProperty -Name Version, Release -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^(?!S)\d+' } | Sort-Object Version -Descending | Select-Object -First 1 if ($netVersions.Release -ge 528040) { return [Version]"4.8" } elseif ($netVersions.Release -ge 461808) { return [Version]"4.7.2" } elseif ($netVersions.Release -ge 460798) { return [Version]"4.7" } elseif ($netVersions.Release -ge 394802) { return [Version]"4.6.2" } elseif ($netVersions.Release -ge 394254) { return [Version]"4.6.1" } elseif ($netVersions.Release -ge 393295) { return [Version]"4.6" } else { return [Version]$netVersions.Version } } catch { return [Version]"0.0" } } |