Private/Get-WUPendingUpdates.ps1
function Get-WUPendingUpdates { <# .SYNOPSIS Retrieves information about pending Windows Updates. .DESCRIPTION Uses the Windows Update API to check for pending updates including their status, size, and installation requirements. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $pendingUpdates = Get-WUPendingUpdates -LogPath "C:\Logs\wu.log" .NOTES This is a private function used internally by the WindowsUpdateTools module. Returns array of pending update objects with detailed information. #> [CmdletBinding()] param( [string]$LogPath ) Write-WULog -Message "Checking for pending Windows Updates" -LogPath $LogPath $pendingUpdates = @() try { # Create Windows Update session $updateSession = New-Object -ComObject Microsoft.Update.Session $updateSearcher = $updateSession.CreateUpdateSearcher() Write-WULog -Message "Searching for pending updates..." -LogPath $LogPath # Search for updates that are not installed $searchResult = $updateSearcher.Search("IsInstalled=0") if ($searchResult.Updates.Count -eq 0) { Write-WULog -Message "No pending updates found" -LogPath $LogPath return $pendingUpdates } Write-WULog -Message "Found $($searchResult.Updates.Count) pending updates" -LogPath $LogPath # Process each pending update foreach ($update in $searchResult.Updates) { try { # Calculate update size $sizeKB = if ($update.MaxDownloadSize -gt 0) { [math]::Round($update.MaxDownloadSize / 1KB, 1) } else { 0 } $sizeMB = if ($sizeKB -gt 0) { [math]::Round($sizeKB / 1024, 1) } else { 0 } # Determine update category $categories = @() if ($update.Categories) { foreach ($category in $update.Categories) { $categories += $category.Name } } # Check if update is downloaded $downloadStatus = "Not Downloaded" if ($update.IsDownloaded) { $downloadStatus = "Downloaded" } elseif ($update.DownloadContents.Count -gt 0) { $downloadStatus = "Partially Downloaded" } # Determine update severity/importance $importance = "Unknown" if ($update.MsrcSeverity) { $importance = $update.MsrcSeverity } elseif ($update.AutoSelectOnWebSites) { $importance = "Important" } else { $importance = "Optional" } # Check for reboot requirement $rebootRequired = $false if ($update.InstallationBehavior) { $rebootRequired = $update.InstallationBehavior.RebootBehavior -ne 0 } # Extract KB number if available $kbNumber = $null if ($update.Title -match 'KB(\d+)') { $kbNumber = "KB$($matches[1])" } # Create update object $updateInfo = [PSCustomObject]@{ Title = $update.Title KBNumber = $kbNumber Description = $update.Description Categories = $categories -join ', ' Importance = $importance SizeKB = $sizeKB SizeMB = $sizeMB DownloadStatus = $downloadStatus IsDownloaded = $update.IsDownloaded RebootRequired = $rebootRequired IsHidden = $update.IsHidden IsMandatory = $update.IsMandatory ReleaseDate = $update.LastDeploymentChangeTime SupportUrl = $update.SupportUrl UpdateID = $update.Identity.UpdateID RevisionNumber = $update.Identity.RevisionNumber } $pendingUpdates += $updateInfo # Log update details Write-WULog -Message " Update: $($update.Title)" -LogPath $LogPath Write-WULog -Message " Size: $sizeMB MB, Status: $downloadStatus, Importance: $importance" -LogPath $LogPath if ($rebootRequired) { Write-WULog -Message " Reboot required after installation" -LogPath $LogPath } } catch { Write-WULog -Message "Error processing update '$($update.Title)': $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Summary statistics $totalSizeMB = ($pendingUpdates | Measure-Object -Property SizeMB -Sum).Sum $downloadedCount = ($pendingUpdates | Where-Object { $_.IsDownloaded }).Count $importantCount = ($pendingUpdates | Where-Object { $_.Importance -in @('Critical', 'Important') }).Count $rebootRequiredCount = ($pendingUpdates | Where-Object { $_.RebootRequired }).Count Write-WULog -Message "Pending updates summary:" -LogPath $LogPath Write-WULog -Message " Total updates: $($pendingUpdates.Count)" -LogPath $LogPath Write-WULog -Message " Total size: $([math]::Round($totalSizeMB, 1)) MB" -LogPath $LogPath Write-WULog -Message " Already downloaded: $downloadedCount" -LogPath $LogPath Write-WULog -Message " Important/Critical: $importantCount" -LogPath $LogPath Write-WULog -Message " Requiring reboot: $rebootRequiredCount" -LogPath $LogPath # Check for stuck downloads $partialDownloads = $pendingUpdates | Where-Object { $_.DownloadStatus -eq "Partially Downloaded" } if ($partialDownloads) { Write-WULog -Message " $($partialDownloads.Count) updates have partial downloads (may indicate download issues)" -Level Warning -LogPath $LogPath } # Check for very old pending updates $oldUpdates = $pendingUpdates | Where-Object { $_.ReleaseDate -and (Get-Date) - $_.ReleaseDate -gt [TimeSpan]::FromDays(30) } if ($oldUpdates) { Write-WULog -Message " $($oldUpdates.Count) updates are over 30 days old" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Error checking for pending updates: $($_.Exception.Message)" -Level Error -LogPath $LogPath # Try alternative method using WUA API try { Write-WULog -Message "Attempting alternative update check method..." -LogPath $LogPath $updateServiceManager = New-Object -ComObject Microsoft.Update.ServiceManager $updateService = $updateServiceManager.Services | Where-Object { $_.IsDefaultAUService } if ($updateService) { Write-WULog -Message "Using update service: $($updateService.Name)" -LogPath $LogPath } else { Write-WULog -Message "Could not identify default update service" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Alternative update check method also failed: $($_.Exception.Message)" -Level Error -LogPath $LogPath } } return $pendingUpdates } |