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
}