Private/Get-WUWindows11ISO-Enhanced.ps1

function Get-WUWindows11ISO-Enhanced {
    <#
    .SYNOPSIS
        Enhanced PowerShell 5.1 compatible Windows 11 ISO download with improved reliability.
 
    .DESCRIPTION
        Downloads Windows 11 ISO using Fido script with enhanced error handling, retry logic,
        and PowerShell 5.1 compatibility. Includes fallback methods and better file detection.
 
    .PARAMETER OutputPath
        Directory where the ISO will be downloaded. Default: C:\Temp
 
    .PARAMETER Edition
        Windows 11 edition to download. Default: Pro
 
    .PARAMETER Language
        Language for the ISO. Default: Auto-detected
 
    .PARAMETER LogPath
        Path to the log file for detailed logging.
 
    .EXAMPLE
        $isoPath = Get-WUWindows11ISO-Enhanced -OutputPath "C:\Temp" -LogPath "C:\Logs\wu.log"
 
    .NOTES
        Enhanced for PowerShell 5.1 compatibility and improved reliability.
        Includes automatic retry logic and better error handling for Fido restrictions.
    #>


    [CmdletBinding()]
    param(
        [string]$OutputPath = "C:\Temp",
        [ValidateSet('Home', 'Pro', 'Enterprise', 'Education')]
        [string]$Edition = "Pro",
        [string]$Language,
        [string]$LogPath
    )
    
    # Helper function for PS 5.1 compatible language detection
    function Get-SystemLanguageForFido-PS51 {
        param([string]$LogPath)
        
        try {
            # Get system culture using PS 5.1 compatible method
            $culture = Get-Culture
            $cultureName = $culture.Name
            
            Write-WULog -Message "Detecting system language: $cultureName" -LogPath $LogPath
            
            # Simple language mapping for PS 5.1
            switch -Regex ($cultureName) {
                '^en-US' { return 'English' }
                '^en-GB|^en-AU|^en-CA' { return 'English International' }
                '^en' { return 'English' }
                '^de' { return 'German' }
                '^fr-CA' { return 'French Canadian' }
                '^fr' { return 'French' }
                '^es-MX' { return 'Spanish (Mexico)' }
                '^es' { return 'Spanish' }
                '^it' { return 'Italian' }
                '^pt-BR' { return 'Brazilian Portuguese' }
                '^pt' { return 'Portuguese' }
                '^nl' { return 'Dutch' }
                '^sv' { return 'Swedish' }
                '^da' { return 'Danish' }
                '^no|^nb' { return 'Norwegian' }
                '^fi' { return 'Finnish' }
                '^pl' { return 'Polish' }
                '^ru' { return 'Russian' }
                '^ja' { return 'Japanese' }
                '^ko' { return 'Korean' }
                '^zh-CN|^zh-Hans' { return 'Chinese (Simplified)' }
                '^zh-TW|^zh-Hant' { return 'Chinese (Traditional)' }
                default { 
                    Write-WULog -Message "No mapping found for $cultureName, defaulting to English" -Level Warning -LogPath $LogPath
                    return 'English' 
                }
            }
        }
        catch {
            Write-WULog -Message "Error detecting language: $($_.Exception.Message), defaulting to English" -Level Warning -LogPath $LogPath
            return 'English'
        }
    }
    
    # Enhanced Fido download with PS 5.1 compatibility
    function Invoke-FidoDownload-PS51 {
        param(
            [string]$OutputPath,
            [string]$Edition,
            [string]$Language,
            [string]$LogPath
        )
        
        Write-WULog -Message "Starting enhanced Fido download (PS 5.1 compatible)..." -LogPath $LogPath
        
        try {
            # Ensure output directory exists
            if (-not (Test-Path $OutputPath)) {
                New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null
                Write-WULog -Message "Created output directory: $OutputPath" -LogPath $LogPath
            }
            
            # Download Fido script with PS 5.1 compatible TLS
            $fidoPath = Join-Path $OutputPath "Fido.ps1"
            
            if (-not (Test-Path $fidoPath)) {
                Write-WULog -Message "Downloading Fido script..." -LogPath $LogPath
                
                # PS 5.1 compatible TLS setup
                $originalProtocol = [Net.ServicePointManager]::SecurityProtocol
                try {
                    # Use this instead of [Enum]::ToObject for PS 5.1 compatibility
                    [Net.ServicePointManager]::SecurityProtocol = 'Tls12'
                    
                    $fidoUrl = "https://github.com/pbatard/Fido/raw/master/Fido.ps1"
                    $webClient = New-Object System.Net.WebClient
                    
                    $webClient.DownloadFile($fidoUrl, $fidoPath)
                    Write-WULog -Message "Fido script downloaded successfully" -LogPath $LogPath
                }
                finally {
                    [Net.ServicePointManager]::SecurityProtocol = $originalProtocol
                    if ($webClient) { $webClient.Dispose() }
                }
            }
            
            # Clean up any existing ISOs to avoid conflicts
            $existingIsos = Get-ChildItem -Path $OutputPath -Filter "*.iso" -ErrorAction SilentlyContinue
            foreach ($iso in $existingIsos) {
                try {
                    Remove-Item -Path $iso.FullName -Force -ErrorAction SilentlyContinue
                    Write-WULog -Message "Removed existing ISO: $($iso.Name)" -LogPath $LogPath
                } catch {
                    Write-WULog -Message "Could not remove existing ISO: $($iso.Name)" -Level Warning -LogPath $LogPath
                }
            }
            
            # Execute Fido with retry logic
            $maxRetries = 3
            $retryDelay = 30
            $downloadSuccess = $false
            $lastError = $null
            
            for ($attempt = 1; $attempt -le $maxRetries; $attempt++) {
                try {
                    Write-WULog -Message "Fido download attempt $attempt of $maxRetries..." -LogPath $LogPath
                    
                    # Store current location and change to output directory
                    $originalLocation = Get-Location
                    Set-Location -Path $OutputPath
                    
                    try {
                        # Build Fido command - simplified for reliability
                        $fidoArgs = @(
                            '-Win', 'Windows 11'
                            '-Rel', 'Latest'
                            '-Ed', $Edition
                            '-Lang', $Language
                            '-Arch', 'x64'
                        )
                        
                        Write-WULog -Message "Executing Fido with args: $($fidoArgs -join ' ')" -LogPath $LogPath
                        
                        # Use Start-Process for better control in PS 5.1
                        $processArgs = @{
                            FilePath = 'powershell.exe'
                            ArgumentList = @('-ExecutionPolicy', 'Bypass', '-File', $fidoPath) + $fidoArgs
                            Wait = $true
                            PassThru = $true
                            NoNewWindow = $true
                            RedirectStandardOutput = "$OutputPath\fido_output.txt"
                            RedirectStandardError = "$OutputPath\fido_error.txt"
                        }
                        
                        $fidoProcess = Start-Process @processArgs
                        $fidoExitCode = $fidoProcess.ExitCode
                        
                        Write-WULog -Message "Fido exit code: $fidoExitCode" -LogPath $LogPath
                        
                        # Read output for diagnostics
                        $fidoOutput = ""
                        $fidoError = ""
                        
                        if (Test-Path "$OutputPath\fido_output.txt") {
                            $fidoOutput = Get-Content "$OutputPath\fido_output.txt" -Raw -ErrorAction SilentlyContinue
                        }
                        if (Test-Path "$OutputPath\fido_error.txt") {
                            $fidoError = Get-Content "$OutputPath\fido_error.txt" -Raw -ErrorAction SilentlyContinue
                        }
                        
                        if ($fidoExitCode -eq 0) {
                            # Look for downloaded ISO
                            Start-Sleep -Seconds 5  # Give filesystem time to update
                            
                            $newIsos = Get-ChildItem -Path $OutputPath -Filter "*.iso" -ErrorAction SilentlyContinue |
                                      Where-Object { $_.Length -gt 3GB } |  # Minimum reasonable size
                                      Sort-Object LastWriteTime -Descending
                            
                            if ($newIsos) {
                                $downloadedIso = $newIsos[0]
                                $fileSizeGB = [math]::Round($downloadedIso.Length / 1GB, 2)
                                
                                Write-WULog -Message "SUCCESS: Downloaded Windows 11 ISO: $($downloadedIso.Name)" -LogPath $LogPath
                                Write-WULog -Message "ISO size: $fileSizeGB GB" -LogPath $LogPath
                                
                                $downloadSuccess = $true
                                return $downloadedIso.FullName
                            } else {
                                $lastError = "No ISO file found after successful Fido execution"
                                Write-WULog -Message $lastError -Level Warning -LogPath $LogPath
                            }
                        } else {
                            # Check for specific errors
                            $combinedOutput = "$fidoOutput $fidoError".ToLower()
                            
                            if ($combinedOutput -match "715-123130" -or $combinedOutput -match "banned" -or $combinedOutput -match "restricted") {
                                $lastError = "Microsoft server restriction detected (Error 715-123130). Try again later or use alternative method."
                                Write-WULog -Message $lastError -Level Warning -LogPath $LogPath
                                
                                # Wait longer before retry for server restrictions
                                if ($attempt -lt $maxRetries) {
                                    Write-WULog -Message "Waiting 120 seconds before retry due to server restriction..." -LogPath $LogPath
                                    Start-Sleep -Seconds 120
                                }
                            } else {
                                $lastError = "Fido failed with exit code $fidoExitCode. Output: $fidoOutput Error: $fidoError"
                                Write-WULog -Message $lastError -Level Warning -LogPath $LogPath
                                
                                # Standard retry delay
                                if ($attempt -lt $maxRetries) {
                                    Write-WULog -Message "Waiting $retryDelay seconds before retry..." -LogPath $LogPath
                                    Start-Sleep -Seconds $retryDelay
                                }
                            }
                        }
                    }
                    finally {
                        Set-Location -Path $originalLocation
                        
                        # Clean up temp files
                        Remove-Item "$OutputPath\fido_output.txt" -Force -ErrorAction SilentlyContinue
                        Remove-Item "$OutputPath\fido_error.txt" -Force -ErrorAction SilentlyContinue
                    }
                } catch {
                    $lastError = "Exception during Fido execution: $($_.Exception.Message)"
                    Write-WULog -Message $lastError -Level Warning -LogPath $LogPath
                    
                    if ($attempt -lt $maxRetries) {
                        Start-Sleep -Seconds $retryDelay
                    }
                }
            }
            
            if (-not $downloadSuccess) {
                throw "All Fido download attempts failed. Last error: $lastError"
            }
        }
        catch {
            Write-WULog -Message "Enhanced Fido download failed: $($_.Exception.Message)" -Level Error -LogPath $LogPath
            throw
        }
    }
    
    # Create fallback download helper (PS 5.1 compatible)
    function New-FallbackDownloadHelper {
        param(
            [string]$OutputPath,
            [string]$Edition,
            [string]$Language,
            [string]$LogPath
        )
        
        Write-WULog -Message "Creating fallback download helper..." -LogPath $LogPath
        
        $helperScript = @"
@echo off
title Windows 11 ISO Download Helper - PowerShell 5.1 Compatible
color 0B
echo =============================================================================
echo WINDOWS 11 ISO DOWNLOAD ALTERNATIVES
echo =============================================================================
echo.
echo Microsoft has restricted automated downloads for your IP/region.
echo Use these proven alternatives to download Windows 11 24H2:
echo.
echo =============================================================================
echo METHOD 1: RUFUS (RECOMMENDED - BYPASSES ALL RESTRICTIONS)
echo =============================================================================
echo 1. Download Rufus from: https://rufus.ie/
echo 2. Run Rufus, click dropdown arrow next to 'SELECT'
echo 3. Choose 'DOWNLOAD'
echo 4. Select: Windows 11, $Language, $Edition, x64
echo 5. Rufus downloads directly from Microsoft bypassing restrictions
echo.
start "" "https://rufus.ie/"
echo.
echo =============================================================================
echo METHOD 2: MICROSOFT DIRECT (WITH MOBILE USER AGENT)
echo =============================================================================
echo 1. Open Chrome/Edge Developer Tools (F12)
echo 2. Click Device Toolbar (phone icon)
echo 3. Select any mobile device (iPhone, Android)
echo 4. Navigate to: https://www.microsoft.com/software-download/windows11
echo 5. Download should be available without restrictions
echo.
start "" "https://www.microsoft.com/software-download/windows11"
echo.
echo =============================================================================
echo METHOD 3: TECHBENCH BY ADGUARD (DIRECT LINKS)
echo =============================================================================
echo 1. Visit: https://tb.rg-adguard.net/public.php
echo 2. Select: Windows 11, $Edition, $Language, x64
echo 3. Get direct Microsoft download link
echo.
start "" "https://tb.rg-adguard.net/public.php"
echo.
echo =============================================================================
echo METHOD 4: UUP DUMP (MICROSOFT UPDATE PACKAGES)
echo =============================================================================
echo 1. Visit: https://uupdump.net/
echo 2. Search: Windows 11 24H2
echo 3. Select language: $Language
echo 4. Download conversion package and run script
echo.
start "" "https://uupdump.net/"
echo.
echo =============================================================================
echo All methods opened. Save ISO to: $OutputPath
echo Recommended: Use Rufus method for best reliability
echo =============================================================================
pause
"@

        
        $helperPath = Join-Path $OutputPath "Windows11_Download_Helper.bat"
        $helperScript | Out-File -FilePath $helperPath -Encoding ASCII -Force
        
        Write-WULog -Message "Created download helper: $helperPath" -LogPath $LogPath
        return $helperPath
    }
    
    # Main execution
    Write-WULog -Message "Starting enhanced Windows 11 ISO download..." -LogPath $LogPath
    
    # Validate output path
    try {
        if (-not (Test-Path $OutputPath -IsValid)) {
            $OutputPath = "C:\Temp"
            Write-WULog -Message "Invalid output path, using C:\Temp" -Level Warning -LogPath $LogPath
        }
        
        if (-not (Test-Path $OutputPath)) {
            New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null
        }
    } catch {
        $OutputPath = "C:\Temp"
        New-Item -Path $OutputPath -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null
    }
    
    # Determine language
    if (-not $Language) {
        $Language = Get-SystemLanguageForFido-PS51 -LogPath $LogPath
    }
    
    Write-WULog -Message "Target: Windows 11 $Edition in $Language" -LogPath $LogPath
    Write-WULog -Message "Output Path: $OutputPath" -LogPath $LogPath
    
    # Try enhanced Fido download
    try {
        $result = Invoke-FidoDownload-PS51 -OutputPath $OutputPath -Edition $Edition -Language $Language -LogPath $LogPath
        
        if ($result -and (Test-Path $result) -and $result.EndsWith('.iso')) {
            Write-WULog -Message "Enhanced Fido download completed successfully: $result" -LogPath $LogPath
            return $result
        }
    } catch {
        Write-WULog -Message "Enhanced Fido download failed: $($_.Exception.Message)" -Level Warning -LogPath $LogPath
    }
    
    # Fallback to helper script
    Write-WULog -Message "Creating fallback download helper..." -LogPath $LogPath
    try {
        $helperPath = New-FallbackDownloadHelper -OutputPath $OutputPath -Edition $Edition -Language $Language -LogPath $LogPath
        
        Write-WULog -Message "Fallback helper created: $helperPath" -LogPath $LogPath
        Write-WULog -Message "Please run the helper script to manually download Windows 11 ISO" -Level Warning -LogPath $LogPath
        
        return $helperPath
    } catch {
        Write-WULog -Message "Failed to create fallback helper: $($_.Exception.Message)" -Level Error -LogPath $LogPath
        throw "All download methods failed"
    }
}