0 0

Install all available Windows Updates

Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name PSWindowsUpdate -Force
Import-Module PSWindowsUpdate
Get-WindowsUpdate -AcceptAll -Install

PSWindowsUpdate module:

# Set execution policy
Set-ExecutionPolicy Bypass -Scope Process -Force

# Kill MRT and uninstall
Stop-Process -Name "MRT" -Force -ErrorAction SilentlyContinue
REG ADD "HKLM\SOFTWARE\Policies\Microsoft\MRT" /v "DontOfferThroughWUAU" /t REG_DWORD /d 1 /f
Start-Process "wusa.exe" -ArgumentList "/uninstall /kb:890830 /quiet /norestart" -Wait

# Reset Windows Update components
Write-Host "Resetting Windows Update components..." -ForegroundColor Yellow
Stop-Service wuauserv, bits, cryptsvc -Force
Get-Process trustedinstaller -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue

# Delete Windows Update cache
Remove-Item "$env:SystemRoot\SoftwareDistribution\*" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "$env:SystemRoot\System32\catroot2\*" -Recurse -Force -ErrorAction SilentlyContinue

# Reset Windows Update services to default security descriptors
Start-Process "sc.exe" -ArgumentList "sdset bits D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)"
Start-Process "sc.exe" -ArgumentList "sdset wuauserv D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)"

# Restart services
Start-Service wuauserv, bits, cryptsvc
Start-Process "wuauclt.exe" -ArgumentList "/resetauthorization /detectnow" -Wait

# Install NuGet provider if not present
if (!(Get-PackageProvider -ListAvailable -Name NuGet -ErrorAction SilentlyContinue)) {
   Write-Host "Installing NuGet provider..."
   Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
}

# Import the PSWindowsUpdate module - install if not present
if (!(Get-Module -ListAvailable -Name PSWindowsUpdate)) {
   Write-Host "PSWindowsUpdate module not found. Installing..."
   Install-Module PSWindowsUpdate -Force -Confirm:$false
}
Import-Module PSWindowsUpdate

function Get-WindowsUpdateStatus {
    Write-Host "`nChecking for Windows Updates..." -ForegroundColor Yellow
    
    try {
        # Get available updates with error handling - including all types
        $updates = Get-WindowsUpdate -RootCategories "Critical Updates","Definition Updates","Drivers","Feature Packs","Security Updates","Service Packs","Tools","Update Rollups","Updates","Upgrades" -MicrosoftUpdate -ErrorAction Stop
        
        if ($updates.Count -eq 0) {
            Write-Host "No updates available." -ForegroundColor Green
            return $false
        }
        else {
            Write-Host "`nFound $($updates.Count) update(s):" -ForegroundColor Cyan
            $updates | ForEach-Object {
                Write-Host "- $($_.Title)" -ForegroundColor White
            }
            return $true
        }
    }
    catch {
        Write-Host "Error checking for updates: $_" -ForegroundColor Red
        Write-Host "Attempting to reset Windows Update components..." -ForegroundColor Yellow
        throw
    }
}

function Install-AvailableUpdates {
    Write-Host "`nInstalling Windows Updates..." -ForegroundColor Yellow
    
    try {
        # Install updates and reboot if required - including all types
        $installResult = Install-WindowsUpdate -RootCategories "Critical Updates","Definition Updates","Drivers","Feature Packs","Security Updates","Service Packs","Tools","Update Rollups","Updates","Upgrades" -MicrosoftUpdate -AcceptAll -AutoReboot:$true -Verbose -ErrorAction Stop
        
        if ($installResult.Count -gt 0) {
            Write-Host "`nInstallation Summary:" -ForegroundColor Cyan
            $installResult | ForEach-Object {
                Write-Host "- $($_.Title): $($_.Result)" -ForegroundColor White
            }
            
            # Check if reboot is required
            if (Get-WURebootStatus -Silent) {
                Write-Host "`nSystem will restart automatically to complete updates." -ForegroundColor Red
                Start-Sleep -Seconds 10  # Give time to read the message
                Restart-Computer -Force
            }
        }
    }
    catch {
        Write-Host "Error installing updates: $_" -ForegroundColor Red
        throw
    }
}

# Main execution
try {
   if (Get-WindowsUpdateStatus) {
       Install-AvailableUpdates
   }
} catch {
   Write-Host "An error occurred: $_" -ForegroundColor Red
   Write-Host "Please ensure you're running PowerShell as Administrator." -ForegroundColor Red
}

Oneliner Windows Update Session:

(Invoke-Command -ScriptBlock {try { $Session = New-Object -ComObject Microsoft.Update.Session; $Searcher = $Session.CreateUpdateSearcher(); $SearchResult = $Searcher.Search("IsInstalled=0"); $UpdatesToDownload = New-Object -ComObject Microsoft.Update.UpdateColl; if($SearchResult.Updates.Count -eq 0) { Write-Host "No updates found." } else { foreach($Update in $SearchResult.Updates){ if($Update.IsInstalled -eq $false){ $UpdatesToDownload.Add($Update); Write-Host "Found update: $($Update.Title)" } }; if($UpdatesToDownload.Count -gt 0) { $Downloader = $Session.CreateUpdateDownloader(); $Downloader.Updates = $UpdatesToDownload; Write-Host "Downloading..."; $Downloader.Download(); $Installer = $Session.CreateUpdateInstaller(); $Installer.Updates = $UpdatesToDownload; Write-Host "Installing..."; $InstallResult = $Installer.Install(); Write-Host "`nInstallation Result: $($InstallResult.HResult)" } else { Write-Host "System is up to date." } } } catch { Write-Host "Error: $($_.Exception.Message)" }})

Combined v3:

reg delete "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate" /f
Set-ExecutionPolicy Bypass -Scope Process -Force
Stop-Process -Name "MRT" -Force -ErrorAction SilentlyContinue
REG ADD "HKLM\SOFTWARE\Policies\Microsoft\MRT" /v "DontOfferThroughWUAU" /t REG_DWORD /d 1 /f
Start-Process "wusa.exe" -ArgumentList "/uninstall /kb:890830 /quiet /norestart" -Wait
Write-Host "Resetting Windows Update components..." -ForegroundColor Yellow
Stop-Service wuauserv, bits, cryptsvc -Force
Get-Process trustedinstaller -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
Remove-Item "$env:SystemRoot\SoftwareDistribution\*" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "$env:SystemRoot\System32\catroot2\*" -Recurse -Force -ErrorAction SilentlyContinue
Start-Process "sc.exe" -ArgumentList "sdset bits D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)"
Start-Process "sc.exe" -ArgumentList "sdset wuauserv D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)"
Start-Service wuauserv, bits, cryptsvc
Start-Process "wuauclt.exe" -ArgumentList "/resetauthorization /detectnow" -Wait
(Invoke-Command -ScriptBlock {try { $Session = New-Object -ComObject Microsoft.Update.Session; $Searcher = $Session.CreateUpdateSearcher(); $SearchResult = $Searcher.Search("IsInstalled=0"); $UpdatesToDownload = New-Object -ComObject Microsoft.Update.UpdateColl; if($SearchResult.Updates.Count -eq 0) { Write-Host "No updates found." } else { foreach($Update in $SearchResult.Updates){ if($Update.IsInstalled -eq $false){ $UpdatesToDownload.Add($Update); Write-Host "Found update: $($Update.Title)" } }; if($UpdatesToDownload.Count -gt 0) { $Downloader = $Session.CreateUpdateDownloader(); $Downloader.Updates = $UpdatesToDownload; Write-Host "Downloading..."; $Downloader.Download(); $Installer = $Session.CreateUpdateInstaller(); $Installer.Updates = $UpdatesToDownload; Write-Host "Installing..."; $InstallResult = $Installer.Install(); Write-Host "`nInstallation Result: $($InstallResult.HResult)" } else { Write-Host "System is up to date." } } } catch { Write-Host "Error: $($_.Exception.Message)" }})

Only list updates, do not install:
(Invoke-Command -ScriptBlock {
    try { 
        $Session = New-Object -ComObject Microsoft.Update.Session
        $Searcher = $Session.CreateUpdateSearcher()
        $SearchResult = $Searcher.Search("IsInstalled=0")
        
        if($SearchResult.Updates.Count -eq 0) { 
            Write-Host "No updates found." 
        } else { 
            Write-Host "Available updates:"
            Write-Host "=================="
            foreach($Update in $SearchResult.Updates){
                if($Update.IsInstalled -eq $false){
                    Write-Host "- $($Update.Title)"
                }
            }
            Write-Host "`nTotal updates available: $($SearchResult.Updates.Count)"
        }
    } catch { 
        Write-Host "Error: $($_.Exception.Message)" 
    }
})

V4 RMM:
# Suppress all verbose output
$ProgressPreference = 'SilentlyContinue'
$WarningPreference = 'SilentlyContinue'
$VerbosePreference = 'SilentlyContinue'
$InformationPreference = 'SilentlyContinue'
$ErrorActionPreference = 'SilentlyContinue'

# Modern Windows 11 Update reset - using new cmdlets where available
try {
    # Use Windows 11's native reset capabilities first
    Reset-WindowsUpdateComponents -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
} catch {
    # Fallback to manual reset if cmdlet not available
}

# Stop Windows Update services - suppress all output
Stop-Service UsoSvc, WaaSMedicSvc, wuauserv, bits, cryptsvc, msiserver -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
Get-Process MoUsoCoreWorker, UsoClient, wuauclt -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue

# Clear Windows 11 update caches and temp files
Remove-Item "$env:SystemRoot\SoftwareDistribution" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "$env:SystemRoot\System32\catroot2" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "$env:ProgramData\USOPrivate\UpdateStore" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "$env:ProgramData\USOShared\Logs" -Recurse -Force -ErrorAction SilentlyContinue

# Reset Windows Update settings in registry for Windows 11 - suppress all output
$null = Start-Process "reg.exe" -ArgumentList "DELETE `"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate`" /v `"SusClientId`" /f" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
$null = Start-Process "reg.exe" -ArgumentList "DELETE `"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate`" /v `"SusClientIdValidation`" /f" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
$null = Start-Process "reg.exe" -ArgumentList "DELETE `"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired`" /f" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null

# Re-register critical Windows 11 Update components - suppress all output
$modernDlls = @('wuapi.dll','wuaueng.dll','wucltux.dll','wups.dll','wups2.dll','wuweb.dll','qmgr.dll','qmgrprxy.dll','wuwebv.dll','wudriver.dll','wuapicore.dll')
foreach ($dll in $modernDlls) {
    $null = Start-Process "regsvr32.exe" -ArgumentList "/s $dll" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
}

# Reset services to default state - suppress all output
$null = Start-Process "sc.exe" -ArgumentList "config UsoSvc start= demand" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
$null = Start-Process "sc.exe" -ArgumentList "config WaaSMedicSvc start= demand" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null

# Restart services in proper order for Windows 11 - suppress all output
Start-Service cryptsvc -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
Start-Service msiserver -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
Start-Service bits -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
Start-Service wuauserv -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
Start-Service UsoSvc -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
Start-Service WaaSMedicSvc -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null

# Force Windows 11 update detection using modern methods - suppress all output
$null = Start-Process "UsoClient.exe" -ArgumentList "ScanInstallWait" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
$null = Start-Process "UsoClient.exe" -ArgumentList "RefreshSettings" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null

# Install PSWindowsUpdate with modern PowerShell practices for Windows 11 - suppress all output
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Ensure NuGet provider is installed first
try {
    if (!(Get-PackageProvider -ListAvailable -Name NuGet -ErrorAction SilentlyContinue)) {
        Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser -Confirm:$false -WarningAction SilentlyContinue | Out-Null
    }
} catch { $null = $_ }

# Install PSWindowsUpdate module - try multiple approaches
$moduleInstalled = $false

# Method 1: Try CurrentUser scope first
try {
    if (!(Get-Module -ListAvailable -Name PSWindowsUpdate -ErrorAction SilentlyContinue)) {
        Install-Module PSWindowsUpdate -Force -Confirm:$false -Scope CurrentUser -AllowClobber -SkipPublisherCheck -WarningAction SilentlyContinue -ErrorAction Stop | Out-Null
        $moduleInstalled = $true
    } else {
        $moduleInstalled = $true
    }
} catch {
    # Method 2: Try AllUsers scope if CurrentUser fails
    try {
        Install-Module PSWindowsUpdate -Force -Confirm:$false -Scope AllUsers -AllowClobber -SkipPublisherCheck -WarningAction SilentlyContinue -ErrorAction Stop | Out-Null
        $moduleInstalled = $true
    } catch {
        $moduleInstalled = $false
    }
}

# Import the module if installation succeeded
if ($moduleInstalled) {
    Import-Module PSWindowsUpdate -Force -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Out-Null
}

function Get-WindowsUpdateStatus {
    try {
        # Check if PSWindowsUpdate module is available
        if (Get-Module -ListAvailable -Name PSWindowsUpdate -ErrorAction SilentlyContinue) {
            # Use Windows 11 optimized update detection - suppress all output
            $null = Start-Process "UsoClient.exe" -ArgumentList "StartScan" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
            Start-Sleep -Seconds 8
            
            # Get all available updates including feature updates for Windows 11
            $updates = Get-WindowsUpdate -MicrosoftUpdate -IgnoreReboot -ErrorAction Stop
            return $updates.Count -gt 0
        } else {
            # Fallback to native Windows Update detection
            $null = Start-Process "UsoClient.exe" -ArgumentList "StartScan" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
            Start-Sleep -Seconds 10
            
            # Check Windows Update registry for pending updates
            $pendingUpdates = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install" -ErrorAction SilentlyContinue
            $lastInstall = if ($pendingUpdates) { [DateTime]$pendingUpdates.LastSuccessTime } else { [DateTime]::MinValue }
            $daysSinceUpdate = ((Get-Date) - $lastInstall).Days
            
            # If no updates in 30+ days, assume updates are available
            return $daysSinceUpdate -gt 30
        }
    }
    catch {
        throw "Failed to check for updates: $($_.Exception.Message)"
    }
}

function Install-AvailableUpdates {
    try {
        # Check if PSWindowsUpdate module is available
        if (Get-Module -ListAvailable -Name PSWindowsUpdate -ErrorAction SilentlyContinue) {
            # Install all updates with Windows 11 optimizations - use specific Force parameters
            $installResult = Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot -ForceInstall -ForceDownload -ErrorAction Stop
            
            # Secondary pass for any missed updates (common in Windows 11)
            Start-Sleep -Seconds 15
            $remainingUpdates = Get-WindowsUpdate -MicrosoftUpdate -IgnoreReboot -ErrorAction SilentlyContinue
            if ($remainingUpdates -and $remainingUpdates.Count -gt 0) {
                Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot -ForceInstall -ForceDownload -ErrorAction SilentlyContinue
            }
        } else {
            # Fallback to native Windows Update using UsoClient
            $null = Start-Process "UsoClient.exe" -ArgumentList "StartDownload" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
            Start-Sleep -Seconds 30
            $null = Start-Process "UsoClient.exe" -ArgumentList "StartInstall" -WindowStyle Hidden -Wait -PassThru -ErrorAction SilentlyContinue 2>$null
            Start-Sleep -Seconds 60
        }
        
        # Check for reboot requirement using Windows 11 method
        if ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -ErrorAction SilentlyContinue) -or 
            (Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -ErrorAction SilentlyContinue)) {
            Start-Sleep -Seconds 20  # Extended time for N-able to capture output
            Restart-Computer -Force
        }
    }
    catch {
        throw "Failed to install updates: $($_.Exception.Message)"
    }
}

# Main execution optimized for Windows 11
try {
    if (Get-WindowsUpdateStatus) {
        Install-AvailableUpdates
        Write-Output "Windows 11 updates installed successfully"
        exit 0
    } else {
        Write-Output "No Windows 11 updates available"
        exit 0
    }
} catch {
    Write-Output "Windows 11 update failed: $($_.Exception.Message)"
    exit 1
}

V4 Manual:
# Enable all verbose output
$ProgressPreference = 'Continue'
$WarningPreference = 'Continue'
$VerbosePreference = 'Continue'
$InformationPreference = 'Continue'
$ErrorActionPreference = 'Continue'

Write-Output "Starting Windows 11 Update reset process..."

# Modern Windows 11 Update reset - using new cmdlets where available
try {
    Write-Output "Attempting to use Windows 11 native reset capabilities..."
    Reset-WindowsUpdateComponents -Verbose -WarningAction Continue
    Write-Output "Native reset completed successfully"
} catch {
    Write-Output "Native reset not available, falling back to manual reset: $($_.Exception.Message)"
}

# Stop Windows Update services - show all output
Write-Output "Stopping Windows Update services..."
Stop-Service UsoSvc, WaaSMedicSvc, wuauserv, bits, cryptsvc, msiserver -Force -Verbose -WarningAction Continue
Write-Output "Stopping related processes..."
Get-Process MoUsoCoreWorker, UsoClient, wuauclt -ErrorAction Continue | Stop-Process -Force -Verbose

# Clear Windows 11 update caches and temp files
Write-Output "Clearing update caches and temp files..."
Write-Output "Removing SoftwareDistribution folder..."
Remove-Item "$env:SystemRoot\SoftwareDistribution" -Recurse -Force -Verbose
Write-Output "Removing catroot2 folder..."
Remove-Item "$env:SystemRoot\System32\catroot2" -Recurse -Force -Verbose
Write-Output "Removing USOPrivate UpdateStore..."
Remove-Item "$env:ProgramData\USOPrivate\UpdateStore" -Recurse -Force -Verbose
Write-Output "Removing USOShared Logs..."
Remove-Item "$env:ProgramData\USOShared\Logs" -Recurse -Force -Verbose

# Reset Windows Update settings in registry for Windows 11 - show all output
Write-Output "Resetting Windows Update registry settings..."
Write-Output "Deleting SusClientId..."
Start-Process "reg.exe" -ArgumentList "DELETE `"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate`" /v `"SusClientId`" /f" -Wait -PassThru
Write-Output "Deleting SusClientIdValidation..."
Start-Process "reg.exe" -ArgumentList "DELETE `"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate`" /v `"SusClientIdValidation`" /f" -Wait -PassThru
Write-Output "Deleting RebootRequired registry key..."
Start-Process "reg.exe" -ArgumentList "DELETE `"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired`" /f" -Wait -PassThru

# Re-register critical Windows 11 Update components - show all output
Write-Output "Re-registering Windows Update DLL components..."
$modernDlls = @('wuapi.dll','wuaueng.dll','wucltux.dll','wups.dll','wups2.dll','wuweb.dll','qmgr.dll','qmgrprxy.dll','wuwebv.dll','wudriver.dll','wuapicore.dll')
foreach ($dll in $modernDlls) {
    Write-Output "Registering $dll..."
    Start-Process "regsvr32.exe" -ArgumentList "/s $dll" -Wait -PassThru
}

# Reset services to default state - show all output
Write-Output "Resetting services to default configuration..."
Write-Output "Configuring UsoSvc..."
Start-Process "sc.exe" -ArgumentList "config UsoSvc start= demand" -Wait -PassThru
Write-Output "Configuring WaaSMedicSvc..."
Start-Process "sc.exe" -ArgumentList "config WaaSMedicSvc start= demand" -Wait -PassThru

# Restart services in proper order for Windows 11 - show all output
Write-Output "Starting services in proper order..."
Write-Output "Starting cryptsvc..."
Start-Service cryptsvc -Verbose
Write-Output "Starting msiserver..."
Start-Service msiserver -Verbose
Write-Output "Starting bits..."
Start-Service bits -Verbose
Write-Output "Starting wuauserv..."
Start-Service wuauserv -Verbose
Write-Output "Starting UsoSvc..."
Start-Service UsoSvc -Verbose
Write-Output "Starting WaaSMedicSvc..."
Start-Service WaaSMedicSvc -Verbose

# Force Windows 11 update detection using modern methods - show all output
Write-Output "Forcing Windows 11 update detection..."
Write-Output "Running UsoClient ScanInstallWait..."
Start-Process "UsoClient.exe" -ArgumentList "ScanInstallWait" -Wait -PassThru
Write-Output "Running UsoClient RefreshSettings..."
Start-Process "UsoClient.exe" -ArgumentList "RefreshSettings" -Wait -PassThru

# Install PSWindowsUpdate with modern PowerShell practices for Windows 11 - show all output
Write-Output "Setting up TLS 1.2 for secure downloads..."
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Ensure NuGet provider is installed first
Write-Output "Checking for NuGet provider..."
try {
    if (!(Get-PackageProvider -ListAvailable -Name NuGet)) {
        Write-Output "Installing NuGet provider..."
        Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser -Confirm:$false -Verbose
        Write-Output "NuGet provider installed successfully"
    } else {
        Write-Output "NuGet provider already available"
    }
} catch { 
    Write-Output "Error with NuGet provider: $($_.Exception.Message)"
}

# Install PSWindowsUpdate module - try multiple approaches
Write-Output "Installing PSWindowsUpdate module..."
$moduleInstalled = $false

# Method 1: Try CurrentUser scope first
try {
    if (!(Get-Module -ListAvailable -Name PSWindowsUpdate)) {
        Write-Output "Installing PSWindowsUpdate for current user..."
        Install-Module PSWindowsUpdate -Force -Confirm:$false -Scope CurrentUser -AllowClobber -SkipPublisherCheck -Verbose
        $moduleInstalled = $true
        Write-Output "PSWindowsUpdate installed successfully for current user"
    } else {
        Write-Output "PSWindowsUpdate module already available"
        $moduleInstalled = $true
    }
} catch {
    Write-Output "Current user installation failed: $($_.Exception.Message)"
    # Method 2: Try AllUsers scope if CurrentUser fails
    try {
        Write-Output "Trying installation for all users..."
        Install-Module PSWindowsUpdate -Force -Confirm:$false -Scope AllUsers -AllowClobber -SkipPublisherCheck -Verbose
        $moduleInstalled = $true
        Write-Output "PSWindowsUpdate installed successfully for all users"
    } catch {
        Write-Output "All users installation also failed: $($_.Exception.Message)"
        $moduleInstalled = $false
    }
}

# Import the module if installation succeeded
if ($moduleInstalled) {
    Write-Output "Importing PSWindowsUpdate module..."
    Import-Module PSWindowsUpdate -Force -Verbose
    Write-Output "PSWindowsUpdate module imported successfully"
} else {
    Write-Output "PSWindowsUpdate module installation failed, will use fallback methods"
}

function Get-WindowsUpdateStatus {
    Write-Output "Checking for available Windows updates..."
    try {
        # Check if PSWindowsUpdate module is available
        if (Get-Module -ListAvailable -Name PSWindowsUpdate) {
            Write-Output "Using PSWindowsUpdate module for update detection..."
            # Use Windows 11 optimized update detection - show all output
            Write-Output "Starting update scan with UsoClient..."
            Start-Process "UsoClient.exe" -ArgumentList "StartScan" -Wait -PassThru
            Write-Output "Waiting for scan to complete..."
            Start-Sleep -Seconds 8
            
            # Get all available updates including feature updates for Windows 11
            Write-Output "Retrieving available updates..."
            $updates = Get-WindowsUpdate -MicrosoftUpdate -IgnoreReboot -Verbose
            Write-Output "Found $($updates.Count) available updates"
            if ($updates.Count -gt 0) {
                Write-Output "Available updates:"
                $updates | ForEach-Object { Write-Output "  - $($_.Title)" }
            }
            return $updates.Count -gt 0
        } else {
            Write-Output "PSWindowsUpdate not available, using fallback detection method..."
            # Fallback to native Windows Update detection
            Write-Output "Starting native update scan..."
            Start-Process "UsoClient.exe" -ArgumentList "StartScan" -Wait -PassThru
            Write-Output "Waiting for native scan to complete..."
            Start-Sleep -Seconds 10
            
            # Check Windows Update registry for pending updates
            Write-Output "Checking registry for update history..."
            $pendingUpdates = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install" -ErrorAction Continue
            $lastInstall = if ($pendingUpdates) { [DateTime]$pendingUpdates.LastSuccessTime } else { [DateTime]::MinValue }
            $daysSinceUpdate = ((Get-Date) - $lastInstall).Days
            
            Write-Output "Last update install: $lastInstall"
            Write-Output "Days since last update: $daysSinceUpdate"
            
            # If no updates in 30+ days, assume updates are available
            $updatesAvailable = $daysSinceUpdate -gt 30
            Write-Output "Updates assumed available: $updatesAvailable"
            return $updatesAvailable
        }
    }
    catch {
        Write-Output "Error checking for updates: $($_.Exception.Message)"
        throw "Failed to check for updates: $($_.Exception.Message)"
    }
}

function Install-AvailableUpdates {
    Write-Output "Starting update installation process..."
    try {
        # Check if PSWindowsUpdate module is available
        if (Get-Module -ListAvailable -Name PSWindowsUpdate) {
            Write-Output "Using PSWindowsUpdate module for installation..."
            # Install all updates with Windows 11 optimizations - use specific Force parameters
            Write-Output "Installing all available updates..."
            $installResult = Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot -ForceInstall -ForceDownload -Verbose
            Write-Output "Initial installation pass completed"
            
            # Secondary pass for any missed updates (common in Windows 11)
            Write-Output "Waiting before checking for remaining updates..."
            Start-Sleep -Seconds 15
            Write-Output "Checking for any remaining updates..."
            $remainingUpdates = Get-WindowsUpdate -MicrosoftUpdate -IgnoreReboot
            if ($remainingUpdates -and $remainingUpdates.Count -gt 0) {
                Write-Output "Found $($remainingUpdates.Count) remaining updates, installing..."
                Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot -ForceInstall -ForceDownload -Verbose
                Write-Output "Secondary installation pass completed"
            } else {
                Write-Output "No remaining updates found"
            }
        } else {
            Write-Output "Using native Windows Update installation..."
            # Fallback to native Windows Update using UsoClient
            Write-Output "Starting download with UsoClient..."
            Start-Process "UsoClient.exe" -ArgumentList "StartDownload" -Wait -PassThru
            Write-Output "Waiting for downloads to complete..."
            Start-Sleep -Seconds 30
            Write-Output "Starting installation with UsoClient..."
            Start-Process "UsoClient.exe" -ArgumentList "StartInstall" -Wait -PassThru
            Write-Output "Waiting for installation to complete..."
            Start-Sleep -Seconds 60
        }
        
        # Check for reboot requirement using Windows 11 method
        Write-Output "Checking if reboot is required..."
        $rebootRequired = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -ErrorAction Continue) -or 
                         (Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -ErrorAction Continue)
        
        if ($rebootRequired) {
            Write-Output "Reboot is required to complete updates"
            Write-Output "Waiting before initiating reboot..."
            Start-Sleep -Seconds 20  # Extended time for capture
            Write-Output "Initiating system reboot..."
            Restart-Computer -Force
        } else {
            Write-Output "No reboot required"
        }
    }
    catch {
        Write-Output "Error during update installation: $($_.Exception.Message)"
        throw "Failed to install updates: $($_.Exception.Message)"
    }
}

# Main execution optimized for Windows 11
Write-Output "Beginning main execution phase..."
try {
    if (Get-WindowsUpdateStatus) {
        Write-Output "Updates are available, proceeding with installation..."
        Install-AvailableUpdates
        Write-Output "Windows 11 updates installed successfully"
    } else {
        Write-Output "No Windows 11 updates available"
    }
} catch {
    Write-Output "Windows 11 update process failed: $($_.Exception.Message)"
    Write-Output "Stack trace: $($_.ScriptStackTrace)"
}