# Exit if not running as administrator
If ( -not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") ) { Write-Output "This script must be run as an administrator" ; Exit 1 }

# Get the operating system CIM instance
Try { $OS = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop }
Catch { Write-Error "Could not get Win32_OperatingSystem CIM instance`n"+$_.Exception.Message ; Exit 1 }

# Exit if the endpoint is not running Windows 10
If ( ($OS.Caption -notmatch "Windows 10") ) { Write-Output "This endpoint is not running Windows 10" ; Exit 1 }
Else { Write-Output "This endpoint is running Windows 10" }

# Exit if the endpoint is not running a Pro/Enterprise edition of Windows
If ( ($OS.Caption -notmatch "Pro") -and ($OS.Caption -notmatch "Enterprise") ) { Write-Output "Only Pro/Enterprise versions of Windows can be upgraded" ; Exit 1 }
Else { Write-Output "This endpoint is running a Pro/Enterprise version of Windows" }

# Exit if the endpoint is a server edition
Try
{
    If ( $OS.ProductType -gt 1 ) { Write-Output "Server operating system will not be upgraded" ; Exit 1 }
    Else { Write-Output "This endpoint is not a server operating system" }
}
Catch { Write-Error "The operating system type could not be determined`n"+$_.Exception.Message ; Exit 1 }

# Exit if the endpoint does not have at least 4GB of RAM
Try
{
    If ( (Get-CimInstance -ClassName Win32_PhysicalMemory -ErrorAction Stop | Measure-Object -Property Capacity -Sum).Sum -lt 4GB ) { Write-Output "This endpoint does not have at least 4GB of RAM" ; Exit 1 }
    Else { Write-Output "This endpoint has at least 4GB of RAM" }
}
Catch { Write-Error "The amount of RAM could not be determined`n"+$_.Exception.Message ; Exit 1 }

# Exit if the endpoint does not have at least 64GB of storage on the system drive
Try
{
    $SystemDrive = $Env:SystemDrive.TrimEnd('\')
    If ( (Get-CimInstance -ClassName Win32_Volume -Filter "DriveLetter = '$SystemDrive'" -ErrorAction Stop).FreeSpace -lt 64GB ) { Write-Output "This endpoint does not have at least 64GB of storage on the system drive" ; Exit 1 }
    Else { Write-Output "This endpoint has at least 64GB of free space on the system drive" }
}
Catch { Write-Error "The free space on the system drive could not be determined`n"+$_.Exception.Message ; Exit 1 }

# Exit if TPM does not exist or is not version 2.0
Try
{
    $TPM2Present = $false
    ForEach ( $specVersion in (Get-CimInstance -Namespace "root\CIMV2\Security\MicrosoftTpm" -Class Win32_Tpm -ErrorAction Stop).SpecVersion )
    {
        If ( $specVersion -ge 2.0 ) { $TPM2Present = $true ; Break }
    }
    If ( $TPM2Present -eq $false ) { Write-Output "TPM does not support version 2.0 specification" ; Exit 1 }
    Else { Write-Output "This endpoint has a TPM compliant with the version 2.0 specification" }
}
Catch { Write-Error "TPM is not present or its version cannot be determined`n"+$_.Exception.Message ; Exit 1 }

# Exit if Secure Boot is not enabled
Try
{
    If ( (Confirm-SecureBootUEFI -ErrorAction Stop) -eq $false ) { Write-Output "Secure Boot is not enabled" ; Exit 1 }
    Else { Write-Output "This endpoint has Secure Boot enabled" }
}
Catch { Write-Output "Secure Boot state cannot be determined.`n"+$_.Exception.Message ; Exit 1 }

# Uninstall previous Windows 11 Update Assistant
$WIAPath = "${Env:ProgramFiles(x86)}\WindowsInstallationAssistant\Windows10UpgraderApp.exe"
If ( Test-Path $WIAPath )
{
    Write-Output "Uninstalling existing Windows Installation Assistant"
    Get-Process -Name "Windows10UpgraderApp" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
    Try { Start-Process $WIAPath -ArgumentList '/ForceUninstall' -Wait }
    Catch { Write-Error $_.Exception.Message ; Exit 1}
} Else { Write-Output "This endpoint does not have the Windows Installation Assistant installed" }

# URL to the Windows Installation Assistant
$URL = 'https://go.microsoft.com/fwlink/?linkid=2171764'

# Download Windows Installation Assistant
$WIAInstaller = "${Env:TEMP}\Windows11InstallationAssistant.exe"
If ( Test-Path $WIAInstaller )
{
    Write-Output "Removing existing Windows Installation Assistant installer: ${WIAInstaller}"
    Remove-Item $WIAInstaller -Force -ErrorAction SilentlyContinue
}
Write-Output "Downloading ${URL} to ""${WIAInstaller}"""
Try { (New-Object System.Net.WebClient).DownloadFile($URL,$WIAInstaller) }
Catch { Write-Error "The Windows Installation Assistant could not be downloaded`n"+$_.Exception.Message ; Exit 1 }

# Install and run the Windows Installation Assistant
If ( -not (Test-Path $WIAInstaller) ) { Write-Error "The Windows Installation Assistant could not be found after successfully downloading" ; Exit 1 }
Write-Output "Launching upgrade"
Try { Start-Process -FilePath $WIAInstaller -ArgumentList "/QuietInstall /SkipEULA /Auto Upgrade /SkipSelfUpdate /ShowProgressInTaskBarIcon /SkipCompatCheck" }
Catch { Write-Output $_.Exception.Message ; Exit 1 }
Exit 0