dist/temp/WindowsUpdateTools/Public/Install-WindowsUpdate.ps1

function Install-WindowsUpdate {
    <#
    .SYNOPSIS
    Downloads and installs Windows Updates using the Microsoft Update API.
 
    .DESCRIPTION
    This function uses the Microsoft.Update.Session COM object to search for, download, and install Window # Download u # Download updates
   
    The download process is optimized using BITS (Background Intelligent Transfer Service) with high priority
    and forced execution to bypass throttling, following best practices from the PSWindowsUpdate module.
    It provides comprehensive logging, error handling, and integration with the WindowsUpdateTools module's diagnostic capabilities.
 
    .PARAMETER Criteria
    The search criteria for updates. Default searches for critical updates that are not hidden or already installed.
 
    .PARAMETER AcceptEula
    Automatically accept End User License Agreements for updates that require them.
 
    .PARAMETER IncludeDrivers
    Include driver updates in the search. By default, only software updates are included.
 
    .PARAMETER SuppressReboot
    Suppress automatic reboot even if updates require it. A warning will be logged instead.
 
    .PARAMETER UseWindowsUpdate
    Force the use of Windows Update servers instead of WSUS (if configured).
 
    .PARAMETER DownloadPriority
    Sets the BITS download priority (1=Low, 2=Normal, 3=High, 4=ExtraHigh). Default is 4 for fastest downloads.
 
    .PARAMETER DisableForcedDownload
    Disables forced download mode. By default, downloads bypass BITS throttling for faster performance.
 
    .PARAMETER MaxRetries
    Maximum number of retry attempts for downloads that fail. Default is 3.
 
    .PARAMETER RetryDelay
    Delay in seconds between retry attempts. Default is 30 seconds.
 
    .EXAMPLE
    Install-WindowsUpdate
    Installs all available critical software updates.
 
    .EXAMPLE
    Install-WindowsUpdate -IncludeDrivers -AcceptEula
    Installs all available updates including drivers, automatically accepting any EULAs.
 
    .EXAMPLE
    Install-WindowsUpdate -Criteria "IsInstalled=0 and Type='Software' and BrowseOnly=0" -SuppressReboot
    Installs software updates with custom criteria and suppresses automatic reboot.
 
    .EXAMPLE
    Install-WindowsUpdate -DownloadPriority 2 -DisableForcedDownload
    Installs updates with normal BITS priority and standard throttling (for bandwidth-limited environments).
 
    .OUTPUTS
    System.Object
    Returns an object containing installation results and statistics.
 
    .NOTES
    Requires administrative privileges and the Windows Update service to be available.
    Uses the Microsoft.Update.Session COM object which is part of the Windows Update Agent.
    Provides user-friendly error messages for common Windows Update failures.
     
    Author: CSOLVE Scripts
    Version: 1.5.7
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [string]$Criteria = "IsHidden=0 and IsInstalled=0 and Type='Software' and BrowseOnly=0",
        
        [Parameter()]
        [switch]$AcceptEula,
        
        [Parameter()]
        [switch]$IncludeDrivers,
        
        [Parameter()]
        [switch]$SuppressReboot,
        
        [Parameter()]
        [switch]$UseWindowsUpdate,
        
        [Parameter()]
        [ValidateRange(1, 4)]
        [int]$DownloadPriority = 4,
        
        [Parameter()]
        [switch]$DisableForcedDownload,
        
        [Parameter()]
        [int]$MaxRetries = 3,
        
        [Parameter()]
        [int]$RetryDelay = 30
    )

    $result = @{
        Success = $false
        SearchCompleted = $false
        UpdatesFound = 0
        UpdatesDownloaded = 0
        UpdatesInstalled = 0
        UpdatesFailed = 0
        RebootRequired = $false
        Errors = @()
        InstalledUpdates = @()
        FailedUpdates = @()
        Duration = $null
    }

    $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()

    try {
        Write-WULog "Starting Windows Update installation process" -Level Info
        
        # Check if running as administrator
        if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
            throw "This function requires administrative privileges. Please run as administrator."
        }

        # Modify criteria to include drivers if requested
        if ($IncludeDrivers) {
            $Criteria = $Criteria -replace "Type='Software'", "(Type='Software' or Type='Driver')"
            Write-WULog "Including driver updates in search criteria" -Level Info
        }

        Write-WULog "Using search criteria: $Criteria" -Level Info

        # Initialize COM objects
        Write-WULog "Initializing Windows Update Session" -Level Info
        $updateSession = New-Object -ComObject "Microsoft.Update.Session"
        $updateSearcher = $updateSession.CreateUpdateSearcher()
        $updateDownloader = $updateSession.CreateUpdateDownloader()
        $updateInstaller = $updateSession.CreateUpdateInstaller()

        # PATCH: Configure downloader properties immediately after creation (like debug tool)
        # Moving this early prevents COM corruption that occurs when set right before download
        try {
            # CRITICAL: Read current values first to stabilize COM object (like debug tool does)
            $currentPriority = $updateDownloader.Priority
            $currentIsForced = $updateDownloader.IsForced
            Write-WULog "Current downloader state: Priority=$currentPriority, IsForced=$currentIsForced" -Level Verbose
            
            $updateDownloader.Priority = $DownloadPriority    # 1=Low, 2=Normal, 3=High, 4=ExtraHigh
            $updateDownloader.IsForced = -not $DisableForcedDownload.IsPresent     # Force download, bypass BITS throttling
            Write-WULog "Early downloader configuration: Priority=$DownloadPriority, IsForced=$(-not $DisableForcedDownload.IsPresent)" -Level Verbose
        } catch {
            Write-WULog "ERROR: Failed to configure downloader properties: $($_.Exception.Message)" -Level Error
            throw "Failed to configure downloader properties: $($_.Exception.Message)"
        }

        # Configure update source
        if ($UseWindowsUpdate) {
            $updateSearcher.ServerSelection = 2  # Use Microsoft Update servers
            Write-WULog "Configured to use Microsoft Update servers" -Level Info
        } else {
            $updateSearcher.ServerSelection = 0  # Use default (may be WSUS if configured)
            Write-WULog "Using default update server configuration" -Level Info
        }

        # Manage Windows Update service and dependencies
        $wuService = Get-Service -Name "wuauserv" -ErrorAction SilentlyContinue
        if (-not $wuService) {
            throw "Windows Update service (wuauserv) not found"
        }

        # Check related services that may affect downloads
        $bitsService = Get-Service -Name "BITS" -ErrorAction SilentlyContinue
        $cryptsvcService = Get-Service -Name "cryptsvc" -ErrorAction SilentlyContinue
        
        Write-WULog "Service Status Check:" -Level Info
        Write-WULog " Windows Update (wuauserv): $($wuService.Status)" -Level Info
        if ($bitsService) { Write-WULog " BITS: $($bitsService.Status)" -Level Info }
        if ($cryptsvcService) { Write-WULog " Cryptographic Services: $($cryptsvcService.Status)" -Level Info }

        $originalServiceState = $wuService.Status
        $originalStartType = $wuService.StartType

        Write-WULog "Windows Update service state: $originalServiceState, Start type: $originalStartType" -Level Info

        # Ensure required services are running
        if ($wuService.Status -ne "Running") {
            if ($wuService.StartType -eq "Disabled") {
                Write-WULog "Temporarily enabling Windows Update service" -Level Warning
                Set-Service -Name "wuauserv" -StartupType Manual
            }
            
            Write-WULog "Starting Windows Update service" -Level Info
            Start-Service -Name "wuauserv" -ErrorAction Stop
        }
        
        # Ensure BITS is running (required for downloads)
        if ($bitsService -and $bitsService.Status -ne "Running") {
            Write-WULog "Starting BITS service (required for downloads)" -Level Info
            try {
                Start-Service -Name "BITS" -ErrorAction Stop
            } catch {
                Write-WULog "Warning: Could not start BITS service: $($_.Exception.Message)" -Level Warning
            }
        }
        
        # Wait for service to fully start
        $timeout = 30
        $elapsed = 0
        while ((Get-Service -Name "wuauserv").Status -ne "Running" -and $elapsed -lt $timeout) {
            Start-Sleep -Seconds 1
            $elapsed++
        }
        
        if ((Get-Service -Name "wuauserv").Status -ne "Running") {
            throw "Failed to start Windows Update service within $timeout seconds"
        }

        # Test COM object before proceeding
        if (-not (Test-WUCOMObject)) {
            Write-WULog -Level Error -Message "Core Windows Update components are not available. Aborting."
            return
        }

        # Search for updates
        Write-WULog "Searching for updates..." -Level Info
        $searchResult = $updateSearcher.Search($Criteria)
        $result.SearchCompleted = $true
        $result.UpdatesFound = $searchResult.Updates.Count

        Write-WULog "Found $($searchResult.Updates.Count) updates" -Level Info

        if ($searchResult.Updates.Count -eq 0) {
            Write-WULog "No updates found matching the specified criteria" -Level Info
            return $result
        }

        # Process each update
        $updateCollection = New-Object -ComObject "Microsoft.Update.UpdateColl"
        $updatesToProcess = @()

        foreach ($update in $searchResult.Updates) {
            $updateInfo = @{
                Title = $update.Title
                Description = $update.Description
                SizeInMB = [math]::Round($update.MaxDownloadSize / 1MB, 2)
                SecurityBulletinIDs = $update.SecurityBulletinIDs
                KBArticleIDs = $update.KBArticleIDs
                Update = $update
            }

            # Handle EULA acceptance
            if (-not $update.EulaAccepted) {
                if ($AcceptEula) {
                    Write-WULog "Accepting EULA for update: $($update.Title)" -Level Warning
                    $update.AcceptEula()
                } else {
                    Write-WULog "Skipping update (EULA not accepted): $($update.Title)" -Level Warning
                    $result.Errors += "EULA not accepted for update: $($update.Title)"
                    continue
                }
            }

            # Check if update requires user input
            if ($update.InstallationBehavior.CanRequestUserInput) {
                Write-WULog "Skipping update (requires user input): $($update.Title)" -Level Warning
                $result.Errors += "Update requires user input: $($update.Title)"
                continue
            }

            $updatesToProcess += $updateInfo
            $updateCollection.Add($update) | Out-Null
        }

        if ($updateCollection.Count -eq 0) {
            Write-WULog "No updates available for installation after filtering" -Level Info
            return $result
        }

        # Download updates
        Write-WULog "Downloading updates..." -Level Info
        $updateDownloader.Updates = $updateCollection
        
        # CRITICAL: Read Updates.Count immediately after assignment to stabilize COM object state
        # This prevents 0x80131501 - the count access "solidifies" the COM object after assignment
        try {
            $updatesCount = $updateDownloader.Updates.Count
            Write-WULog "Successfully assigned $updatesCount updates to downloader" -Level Verbose
        } catch {
            Write-WULog "WARNING: Could not read updates count after assignment - may indicate COM corruption" -Level Warning
        }
        
        
        # PATCH: Removed late Priority/IsForced configuration to prevent COM corruption
        # Configuration moved to early initialization (right after CreateUpdateDownloader)
        # Original problematic code was here:
        # $updateDownloader.Priority = $DownloadPriority
        # $updateDownloader.IsForced = -not $DisableForcedDownload.IsPresent
        Write-WULog "Priority/IsForced configuration moved to early initialization" -Level Verbose        $priorityName = @{1="Low"; 2="Normal"; 3="High"; 4="ExtraHigh"}[$DownloadPriority]
        $forcedStatus = if (-not $DisableForcedDownload.IsPresent) { "Enabled" } else { "Disabled" }
        Write-WULog "Configured downloader: Priority=$priorityName, ForcedDownload=$forcedStatus (BITS optimization)" -Level Info
        
        # Calculate total download size for progress tracking
        $totalSizeBytes = 0
        foreach ($updateInfo in $updatesToProcess) {
            $totalSizeBytes += ($updateInfo.SizeInMB * 1MB)
        }
        $totalSizeMB = [math]::Round($totalSizeBytes / 1MB, 2)
        
        if ($totalSizeMB -gt 0) {
            Write-WULog "Total download size: $totalSizeMB MB" -Level Info
        }
        
        $downloadSuccess = $false
        $retryCount = 0
        
        while (-not $downloadSuccess -and $retryCount -lt $MaxRetries) {
            try {
                $retryCount++
                Write-WULog "Download attempt $retryCount of $MaxRetries" -Level Info
                
                # Validate update collection before download
                Write-WULog "Validating update collection..." -Level Verbose
                # PATCH: Removed count access to prevent COM corruption
                Write-WULog "Update collection validation complete (count access removed to prevent 0x80131501)" -Level Verbose
                Write-WULog "Update downloader object validated (type access removed to prevent COM corruption)" -Level Verbose
                
                # PATCH: Removed updateCollection.Count check to prevent COM corruption
                # if ($updateCollection.Count -eq 0) {
                # throw "Update collection is empty - cannot download"
                # }
                
                # PATCH: Removed update validation loop to prevent COM corruption
                # for ($i = 0; $i -lt $updateCollection.Count; $i++) {
                # $update = $updateCollection.Item($i)
                # Write-WULog "Update $($i + 1): $($update.Title)..." -Level Verbose
                # }
                Write-WULog "Update validation skipped to prevent COM corruption" -Level Verbose
                
                # Start download with progress monitoring (direct execution - no background job)
                $downloadStartTime = Get-Date
                Write-Progress -Activity "Downloading Windows Updates" -Status "Starting download..." -PercentComplete 0
                Write-WULog "Starting download of updates..." -Level Info
                
                # Execute download directly (COM objects can't be serialized to background jobs)
                Write-WULog "STEP 1: About to call updateDownloader.Download()..." -Level Verbose
                
                # PATCH: Removed problematic property access validation that was corrupting COM object
                # The following debug lines were causing 0x80131501 errors:
                # - UpdateDownloader.Updates.Count access
                # - Other property accesses right before Download()
                Write-WULog "STEP 2: All property access validation removed to prevent COM corruption" -Level Verbose
                
                # Add granular debugging to pinpoint exact failure location
                Write-WULog "STEP 3: Starting download attempt with minimal COM interaction..." -Level Verbose
                Write-WULog "STEP 4: No property reads, no validation, direct call only" -Level Verbose
                
                # Attempt download with detailed error reporting
                Write-WULog "STEP 5: Entering try block for Download() call" -Level Verbose
                try {
                    Write-WULog "STEP 6: Inside try block, about to execute Download() method" -Level Verbose
                    Write-WULog "STEP 7: Calling updateDownloader.Download() NOW..." -Level Verbose
                    $downloadResult = $updateDownloader.Download()
                    Write-WULog "STEP 8: Download() method completed successfully!" -Level Verbose
                    Write-WULog "Download method returned successfully" -Level Verbose
                    Write-WULog "DEBUG: Download result type: $($downloadResult.GetType().FullName)" -Level Verbose
                    Write-WULog "DEBUG: Download result code: $($downloadResult.ResultCode)" -Level Verbose
                } catch [System.Management.Automation.MethodInvocationException] {
                    Write-WULog "ERROR: STEP FAILED - COM Method Invocation Exception during Download() call" -Level Error
                    Write-WULog "ERROR: This means the Download() method itself failed to execute" -Level Error
                    Write-WULog "ERROR: Exception Message: $($_.Exception.Message)" -Level Error
                    Write-WULog "ERROR: Inner Exception: $($_.Exception.InnerException.Message)" -Level Error
                    Write-WULog "ERROR: HResult: $($_.Exception.HResult)" -Level Error
                    throw "Download failed due to COM method invocation error: $($_.Exception.Message)"
                } catch [System.Runtime.InteropServices.COMException] {
                    Write-WULog "ERROR: COM Exception during download" -Level Error
                    Write-WULog "ERROR: Exception Message: $($_.Exception.Message)" -Level Error
                    Write-WULog "ERROR: HResult: $($_.Exception.HResult)" -Level Error
                    throw "Download failed due to COM error: $($_.Exception.Message)"
                } catch {
                    Write-WULog "ERROR: Unexpected exception during download" -Level Error
                    Write-WULog "ERROR: Exception Type: $($_.Exception.GetType().FullName)" -Level Error
                    Write-WULog "ERROR: Exception Message: $($_.Exception.Message)" -Level Error
                    Write-WULog "ERROR: HResult: $($_.Exception.HResult)" -Level Error
                    Write-WULog "ERROR: Stack Trace: $($_.Exception.StackTrace)" -Level Error
                    throw "Download failed: $($_.Exception.Message)"
                }
                
                Write-Progress -Activity "Downloading Windows Updates" -Status "Download completed" -PercentComplete 100
                
                $downloadEndTime = Get-Date
                $downloadDuration = $downloadEndTime - $downloadStartTime
                Write-WULog "Download completed in $($downloadDuration.ToString('mm\:ss'))" -Level Info
                
                # Verify download completion
                $allDownloaded = $true
                for ($i = 0; $i -lt $updateCollection.Count; $i++) {
                    $update = $updateCollection.Item($i)
                    if (-not $update.IsDownloaded) {
                        $allDownloaded = $false
                        Write-WULog "Update not fully downloaded: $($update.Title)" -Level Warning
                    }
                }
                
                if ($allDownloaded) {
                    $downloadSuccess = $true
                    Write-WULog "Download completed successfully - all updates verified as downloaded" -Level Info
                } else {
                    $result.Errors += "Verification failed: Some updates were not properly downloaded."
                    Write-WULog "ERROR: Verification failed. Not all updates were downloaded successfully." -Level Error
                    # Do not throw here, let the process continue to the finally block to report results
                }
            } catch {
                $currentHResult = if ($_.Exception.HResult -ne 0) { $_.Exception.HResult } else { $_.Exception.Message }
                
                # Enhanced error logging
                Write-WULog "Exception details:" -Level Verbose
                Write-WULog " Exception Type: $($_.Exception.GetType().FullName)" -Level Verbose
                Write-WULog " HResult: $($_.Exception.HResult)" -Level Verbose
                Write-WULog " Message: $($_.Exception.Message)" -Level Verbose
                Write-WULog " InnerException: $($_.Exception.InnerException)" -Level Verbose
                
                if ($currentHResult -eq -2145124325) {
                    # WU_E_SELFUPDATE_IN_PROGRESS
                    Write-WULog "Windows Update Agent is self-updating. Retry $retryCount of $MaxRetries in $RetryDelay seconds..." -Level Warning
                } elseif ($currentHResult -eq -2146233087) {
                    # Common .NET exception - often indicates COM object issues
                    Write-WULog "COM object method invocation failed. This may indicate:" -Level Error
                    Write-WULog " - Update collection is empty or invalid" -Level Error
                    Write-WULog " - UpdateDownloader COM object is corrupted" -Level Error
                    Write-WULog " - Windows Update service is not running properly" -Level Error
                    Write-WULog "Attempting to recreate COM objects..." -Level Info
                    
                    # PATCH: Avoid COM object recreation and property assignment that causes corruption
                    try {
                        Write-WULog "PATCH: Skipping COM recreation to prevent 0x80131501 corruption" -Level Info
                        # Original problematic code:
                        # $updateSession = New-Object -ComObject "Microsoft.Update.Session"
                        # $updateDownloader = $updateSession.CreateUpdateDownloader()
                        # $updateDownloader.Updates = $updateCollection # <-- THIS CORRUPTS!
                        # $updateDownloader.Priority = $DownloadPriority
                        # $updateDownloader.IsForced = -not $DisableForcedDownload.IsPresent
                        Write-WULog "COM object recreation skipped to prevent corruption" -Level Info
                    } catch {
                        Write-WULog "Failed to recreate COM objects: $($_.Exception.Message)" -Level Error
                    }
                } else {
                    if ($_.Exception.HResult -ne 0) {
                        $errorDescription = Get-WUHResultDescription -HResult $_.Exception.HResult
                    } else {
                        $errorDescription = "Download failed - $($_.Exception.Message)"
                    }
                    Write-WULog "Download failed (attempt $retryCount of $MaxRetries): $errorDescription" -Level Error
                }
                
                if ($retryCount -lt $MaxRetries) {
                    Start-Sleep -Seconds $RetryDelay
                } else {
                    if ($_.Exception.HResult -ne 0) {
                        $errorDescription = Get-WUHResultDescription -HResult $_.Exception.HResult
                        throw "Download failed after $MaxRetries attempts: $errorDescription"
                    } else {
                        throw "Download failed after $MaxRetries attempts - $($_.Exception.Message)"
                    }
                }
            }
        }

        $result.UpdatesDownloaded = $updateCollection.Count

        # Install updates
        if ($PSCmdlet.ShouldProcess("$($updateCollection.Count) Windows Updates", "Install")) {
            # Final validation - ensure all updates are downloaded before installation
            $notDownloaded = @()
            for ($i = 0; $i -lt $updateCollection.Count; $i++) {
                $update = $updateCollection.Item($i)
                if (-not $update.IsDownloaded) {
                    $notDownloaded += $update.Title
                }
            }
            
            if ($notDownloaded.Count -gt 0) {
                $errorMsg = "Cannot install updates that are not fully downloaded: $($notDownloaded -join ', ')"
                Write-WULog $errorMsg -Level Error
                $result.Errors += $errorMsg
                throw $errorMsg
            }
            
            Write-WULog "Installing $($updateCollection.Count) updates..." -Level Info
            $updateInstaller.Updates = $updateCollection
            
            try {
                # Start installation with progress monitoring (direct execution - no background job)
                $installStartTime = Get-Date
                Write-Progress -Activity "Installing Windows Updates" -Status "Starting installation..." -PercentComplete 0
                Write-WULog "Starting installation..." -Level Info
                
                # Execute installation directly (COM objects can't be serialized to background jobs)
                $installResult = $updateInstaller.Install()
                
                Write-Progress -Activity "Installing Windows Updates" -Status "Installation completed" -PercentComplete 100
                Write-Progress -Activity "Installing Windows Updates" -Completed
                
                $installEndTime = Get-Date
                $installDuration = $installEndTime - $installStartTime
                Write-WULog "Installation completed in $($installDuration.ToString('mm\:ss'))" -Level Info
                
                # Debug installation result object
                Write-WULog "Installation result object type: $($installResult.GetType().FullName)" -Level Verbose
                Write-WULog "Installation result code: $($installResult.ResultCode)" -Level Verbose
                Write-WULog "Number of update results: $($installResult.GetUpdateResult.Count)" -Level Verbose
                Write-WULog "Reboot required: $($installResult.RebootRequired)" -Level Verbose
                
                # Process installation results
                for ($i = 0; $i -lt $installResult.GetUpdateResult.Count; $i++) {
                    $updateResult = $installResult.GetUpdateResult($i)
                    $update = $updateCollection.Item($i)
                    
                    Write-WULog "Processing update $($i + 1): $($update.Title)" -Level Verbose
                    Write-WULog "Update result code: $($updateResult.ResultCode)" -Level Verbose
                    Write-WULog "Update HRESULT: $($updateResult.HResult)" -Level Verbose
                    
                    $updateStatus = @{
                        Title = $update.Title
                        ResultCode = $updateResult.ResultCode
                        HResult = $updateResult.HResult
                        RestartRequired = $updateResult.RestartRequired
                    }

                    switch ($updateResult.ResultCode) {
                        1 { # In Progress
                            Write-WULog "WARNING: Installation reports 'In Progress' for: $($update.Title) (This should not happen in synchronous mode)" -Level Warning
                            $result.Errors += "Installation reports 'In Progress' - this indicates a potential issue with the update process"
                            # Don't count as installed - this is an error condition
                        }
                        2 { # Succeeded
                            $result.UpdatesInstalled++
                            $result.InstalledUpdates += $updateStatus
                            Write-WULog "Successfully installed: $($update.Title)" -Level Info
                        }
                        3 { # Succeeded with errors
                            $result.UpdatesInstalled++
                            $result.InstalledUpdates += $updateStatus
                            Write-WULog "Installed with errors: $($update.Title)" -Level Warning
                        }
                        4 { # Failed
                            $result.UpdatesFailed++
                            $result.FailedUpdates += $updateStatus
                            
                            # Get user-friendly error description
                            $errorDescription = Get-WUHResultDescription -HResult $updateResult.HResult
                            Write-WULog "Failed to install: $($update.Title) - $errorDescription" -Level Error
                            $result.Errors += "Failed to install: $($update.Title) - $errorDescription"
                        }
                        5 { # Aborted
                            $result.UpdatesFailed++
                            $result.FailedUpdates += $updateStatus
                            Write-WULog "Installation aborted: $($update.Title)" -Level Error
                            $result.Errors += "Installation aborted: $($update.Title)"
                        }
                        default {
                            Write-WULog "Unknown result code $($updateResult.ResultCode) for: $($update.Title)" -Level Warning
                        }
                    }

                    if ($updateResult.RestartRequired) {
                        $result.RebootRequired = $true
                    }
                }

                # Handle reboot requirement and set success status
                if ($result.RebootRequired) {
                    if ($SuppressReboot) {
                        Write-WULog "Updates installed successfully but a restart is required. Restart has been suppressed." -Level Warning
                    } else {
                        Write-WULog "Updates installed successfully. A restart is required and will be initiated." -Level Warning
                        # Note: In a real implementation, you might want to integrate with your module's reboot handling
                        # For now, we'll just log the requirement
                    }
                } else {
                    Write-WULog "Updates installed successfully. No restart required." -Level Info
                }
                
        # Set success status based on whether any updates were installed or if there were critical errors
        if ($result.UpdatesInstalled -gt 0 -or ($result.UpdatesFound -eq 0 -and $result.Errors.Count -eq 0)) {
            $result.Success = $true
            Write-WULog "Installation operation completed successfully" -Level Info
        } else {
            $result.Success = $false
            Write-WULog "Installation operation completed with errors - initiating automatic repair" -Level Warning
            
            # Automatic repair based on error patterns
            Write-Host "`n" + ("="*60) -ForegroundColor Yellow
            Write-Host " AUTOMATIC REPAIR INITIATED" -ForegroundColor Yellow
            Write-Host ("="*60) -ForegroundColor Yellow
            
            $errorString = $result.Errors -join " "
            $repairAttempted = $false
            
            if ($errorString -match "COMPONENT_STORE|0x80073712|0x800f0982|0x80070490") {
                Write-Host "Component store corruption detected - running component store repair..." -ForegroundColor Yellow
                try {
                    $repairResult = Resolve-WUComponentStore -ForceSSU
                    Write-Host "Component store repair completed with result: $($repairResult.OverallResult)" -ForegroundColor Green
                    $result.Errors += "Auto-repair attempted: Component store repair - $($repairResult.OverallResult)"
                    $repairAttempted = $true
                } catch {
                    Write-Host "Component store repair failed: $($_.Exception.Message)" -ForegroundColor Red
                    $result.Errors += "Auto-repair failed: Component store repair - $($_.Exception.Message)"
                }
            }
            elseif ($errorString -match "NOTDOWNLOADED|DOWNLOAD_FAILED|CONNECTION_ERROR|TIMEOUT") {
                Write-Host "Download/connectivity issues detected - running network troubleshooting..." -ForegroundColor Yellow
                try {
                    $repairResult = Invoke-WUTroubleshooter
                    Write-Host "Network troubleshooting completed" -ForegroundColor Green
                    $result.Errors += "Auto-repair attempted: Network troubleshooting completed"
                    $repairAttempted = $true
                } catch {
                    Write-Host "Network troubleshooting failed: $($_.Exception.Message)" -ForegroundColor Red
                    $result.Errors += "Auto-repair failed: Network troubleshooting - $($_.Exception.Message)"
                }
            }
            elseif ($errorString -match "INSTALL_NOT_ALLOWED|INSTALL_ALREADY_RUNNING") {
                Write-Host "Installation blocking detected - checking for pending operations..." -ForegroundColor Yellow
                try {
                    $pendingUpdates = Get-WUPendingUpdates
                    if ($pendingUpdates.PendingReboot) {
                        Write-Host "Pending reboot detected - restart required before installation" -ForegroundColor Yellow
                        $result.Errors += "Auto-diagnosis: Pending reboot detected - restart required"
                    } else {
                        Write-Host "No pending reboot found - may be another installer running" -ForegroundColor Yellow
                        $result.Errors += "Auto-diagnosis: No pending reboot - check for other installers"
                    }
                    $repairAttempted = $true
                } catch {
                    Write-Host "Pending operation check failed: $($_.Exception.Message)" -ForegroundColor Red
                    $result.Errors += "Auto-diagnosis failed: Pending operation check - $($_.Exception.Message)"
                }
            }
            
            if (-not $repairAttempted) {
                Write-Host "Generic Windows Update failure - running comprehensive repair..." -ForegroundColor Yellow
                try {
                    $repairResult = Invoke-WUComprehensiveRemediation
                    Write-Host "Comprehensive repair completed with result: $($repairResult.OverallResult)" -ForegroundColor Green
                    $result.Errors += "Auto-repair attempted: Comprehensive remediation - $($repairResult.OverallResult)"
                } catch {
                    Write-Host "Comprehensive repair failed: $($_.Exception.Message)" -ForegroundColor Red
                    $result.Errors += "Auto-repair failed: Comprehensive remediation - $($_.Exception.Message)"
                }
            }
            
            Write-Host ("="*60) -ForegroundColor Yellow
            Write-Host ""
        }            } catch {
                if ($_.Exception.HResult -eq -2145124330) {
                    # WU_E_INSTALL_NOT_ALLOWED
                    $errorMsg = Get-WUHResultDescription -HResult $_.Exception.HResult
                    Write-WULog $errorMsg -Level Error
                    $result.Errors += $errorMsg
                } else {
                    $errorDescription = Get-WUHResultDescription -HResult $_.Exception.HResult
                    Write-WULog $errorDescription -Level Error
                    $result.Errors += $errorDescription
                    throw
                }
            }
        }

    } catch {
        # This is the top-level catch block. It ensures a friendly message is always logged.
        $errorMessage = if ($_) {
            if ($_.Exception -and $_.Exception.HResult -ne 0) {
                Get-WUHResultDescription -HResult $_.Exception.HResult
            } else {
                # If a string was thrown, use it directly.
                "Windows Update installation failed: $_"
            }
        } else {
            "An unknown error occurred during Windows Update installation."
        }
        
        Write-WULog $errorMessage -Level Error
        $result.Errors += $errorMessage
        # We do not re-throw here, allowing the 'finally' block to run and return the results object.
    } finally {
        # Restore original service state
        try {
            $currentService = Get-Service -Name "wuauserv" -ErrorAction SilentlyContinue
            if ($currentService -and $originalServiceState -eq "Stopped") {
                Write-WULog "Restoring Windows Update service to original state" -Level Info
                Set-Service -Name "wuauserv" -StartupType $originalStartType
                Stop-Service -Name "wuauserv" -Force -ErrorAction SilentlyContinue
            }
        } catch {
            Write-WULog "Warning: Could not restore original Windows Update service state: $($_.Exception.Message)" -Level Warning
        }

        # Clean up COM objects
        try {
            if ($updateInstaller) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($updateInstaller) | Out-Null }
            if ($updateDownloader) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($updateDownloader) | Out-Null }
            if ($updateSearcher) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($updateSearcher) | Out-Null }
            if ($updateSession) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($updateSession) | Out-Null }
            if ($updateCollection) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($updateCollection) | Out-Null }
        } catch {
            # Ignore COM cleanup errors
        }

        $stopwatch.Stop()
        $result.Duration = $stopwatch.Elapsed
        
        Write-WULog "Windows Update installation completed in $($result.Duration.ToString('hh\:mm\:ss'))" -Level Info
        Write-WULog "Summary - Success: $($result.Success), Found: $($result.UpdatesFound), Downloaded: $($result.UpdatesDownloaded), Installed: $($result.UpdatesInstalled), Failed: $($result.UpdatesFailed)" -Level Info
        
        # Format and display the final report
        Format-WUResult -Result $result
    }

    return $result
}