Initial commit

This commit is contained in:
Ad3t0
2025-03-13 17:17:05 +00:00
commit e6fd0c3011
3 changed files with 1087 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
dev/

996
DirectWindowsUpgrade.ps1 Normal file
View File

@@ -0,0 +1,996 @@
# Direct Windows 11 Upgrade - No GUI
#
# This script performs a silent in-place upgrade to Windows 11, supporting:
# - Upgrading from Windows 10 to Windows 11
# - Upgrading from older Windows 11 versions to newer versions (e.g., 21H2 to 22H2)
# - Completely silent operation with no user interaction required
# - Bypassing TPM, CPU, and other hardware compatibility checks
#
# PROCESS DETAILS:
# - The script will install 7-Zip if not already present (required to extract ISO contents)
# - Total upgrade process takes approximately 1.5 hours to complete
# - By default, the system will automatically reboot when necessary (configurable)
# - No user intervention is required at any point in the process
#
# USAGE NOTES:
# 1. Edit the configuration section below to specify your Windows 11 ISO source
# 2. Make sure to use an ISO containing the Windows 11 version you want to upgrade to
# 3. Recommended ISO source: https://massgrave.dev/genuine-installation-media.html
# 4. Run this script with administrative privileges
#######################################################################
# CONFIGURATION - MODIFY THESE SETTINGS AS NEEDED
#######################################################################
# Specify the Windows 11 ISO source - MODIFY THIS FOR YOUR ENVIRONMENT
# Options:
# 1. Direct download URL (default)
# 2. Local file path (e.g., "C:\Path\To\Windows11.iso")
# 3. Network share (e.g., "\\server\share\Windows11.iso")
#
# IMPORTANT: The ISO must contain the Windows 11 version you want to upgrade to.
# Business editions are recommended as they have fewer issues with silent upgrades.
# You can download official ISOs from: https://massgrave.dev/genuine-installation-media.html
$WIN11_ISO_SOURCE = "https://replace/this/url/with/your/iso/windows.iso"
# WORKING DIRECTORIES - you can modify these if needed
$WORKING_DIR = "C:\Win11Upgrade" # Main working directory
$TEMP_DIR = "C:\Windows\Temp" # Temporary directory
$LOG_FILE = "C:\Win11_Upgrade_Progress.log" # Main log file
$MONITOR_LOG = "C:\Win11_Monitor.log" # Process monitor log file
# BEHAVIOR SETTINGS
$ALLOW_AUTOMATIC_REBOOT = $true # Set to $false to prevent automatic reboots
#######################################################################
# SCRIPT BEGINS HERE - DO NOT MODIFY BELOW THIS LINE UNLESS NECESSARY
#######################################################################
# Ensure running as admin
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Host "ERROR: This script requires administrator privileges." -ForegroundColor Red
Write-Host "Please restart the script with administrator rights." -ForegroundColor Yellow
exit 1
}
# Use the ISO source defined at the top of the script
$isoUrl = $WIN11_ISO_SOURCE
$isoPath = "$TEMP_DIR\windows11.iso"
# Validate the URL or file path before doing anything else
if ($isoUrl -eq "https://replace/this/url/with/your/iso/windows.iso") {
Write-Host "ERROR: You need to replace the placeholder URL in the configuration section." -ForegroundColor Red
Write-Host "Please edit the script and update the `$WIN11_ISO_SOURCE variable with a valid ISO URL or file path." -ForegroundColor Yellow
exit 1
}
# Show confirmation prompt
Write-Host "WARNING: You are about to start an automated Windows 11 upgrade process." -ForegroundColor Yellow
Write-Host ""
Write-Host "The following will occur if you proceed:"
Write-Host "- 7-Zip will be installed (if not already present)"
Write-Host "- System settings will be modified"
Write-Host "- Your PC will reboot when the installation is ready"
Write-Host "- The entire process takes approximately 1.5 hours"
Write-Host ""
Write-Host "IMPORTANT NOTES:" -ForegroundColor Cyan
Write-Host "- Please be patient during the upgrade process"
Write-Host "- As long as SetupHost.exe is running in Task Manager, the upgrade is working"
Write-Host "- The process may appear to stall at times, but this is normal"
Write-Host "- Do not interrupt the process once it has started"
Write-Host ""
$confirmation = Read-Host "Do you want to continue with the Windows 11 upgrade? (y/n)"
if ($confirmation -ne 'y' -and $confirmation -ne 'Y') {
Write-Host "Windows 11 upgrade cancelled by user."
exit 0
}
# Set aggressive compatibility bypass registry keys
Write-Host "Setting comprehensive compatibility bypass registry keys..."
# TPM and basic hardware checks
reg add "HKLM\SYSTEM\Setup\MoSetup" /f /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassTPMCheck /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassSecureBootCheck /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassRAMCheck /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassStorageCheck /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassCPUCheck /d 1 /t reg_dword
# Safeguard overrides
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v DisableWUfBSafeguards /d 1 /t reg_dword
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\UpdatePolicy\Settings" /f /v DisableWUfBSafeguards /d 1 /t reg_dword
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v DisableSafeguards /d 1 /t reg_dword
# Setup compatibility settings
reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreAllWarnings /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreHWRequirements /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreApplicationsOnUpgrade /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreAppsOnUpgrade /d 1 /t reg_dword
reg add "HKLM\SYSTEM\Setup\Status\UninstallWindow" /f /v UninstallActive /d 0 /t reg_dword
# Disable compatibility checks
reg add "HKLM\SYSTEM\Setup" /f /v BypassCompatibilityCheck /d 1 /t reg_dword
# Disable error reporting during upgrade
reg add "HKLM\SOFTWARE\Microsoft\PCHealth\ErrorReporting" /f /v DoReport /d 0 /t reg_dword
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /f /v Disabled /d 1 /t reg_dword
# Skip setup compliance checks
reg add "HKLM\SYSTEM\Setup" /f /v BypassComplianceCheck /d 1 /t reg_dword
# Allow setup to continue despite errors
reg add "HKLM\SYSTEM\Setup" /f /v AllowNonZeroExitStatus /d 1 /t reg_dword
# Disable CEIP during setup
reg add "HKLM\SOFTWARE\Policies\Microsoft\SQMClient\Windows" /f /v CEIPEnable /d 0 /t reg_dword
# Force target platform version
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v TargetReleaseVersion /d 1 /t reg_dword
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v TargetReleaseVersionInfo /d "25H1" /t reg_sz
# Function to validate URL - ensures the URL is reachable before download
function Test-UrlIsValid {
param (
[string]$Url
)
try {
# Simple HEAD request to check if URL is reachable
$request = [System.Net.WebRequest]::Create($Url)
$request.Method = "HEAD"
$request.Timeout = 15000 # 15 seconds timeout
$request.UserAgent = "Mozilla/5.0 Windows PowerShell Script"
# Get the response
$response = $request.GetResponse()
# Check if we can access the URL
$success = $response.StatusCode -eq [System.Net.HttpStatusCode]::OK
# Show file size if available
$contentLength = $response.Headers["Content-Length"]
if ($contentLength) {
$sizeInMB = [math]::Round([long]$contentLength / 1MB, 2)
if ($sizeInMB -gt 1000) {
Write-Host "File size: $([math]::Round($sizeInMB / 1024, 2)) GB" -ForegroundColor Cyan
} else {
Write-Host "File size: $sizeInMB MB" -ForegroundColor Cyan
}
}
# Close the response
$response.Close()
return $success
}
catch {
# Simple error message without details that could cause red dumps
Write-Host "ERROR: Could not access the URL. Please verify it's correct and accessible." -ForegroundColor Red
return $false
}
}
# If the ISO source is a local file or network share, copy it to the temp directory
if (Test-Path $isoUrl) {
Write-Host "Using local/network ISO file: $isoUrl"
# Verify it's an ISO file
$extension = [System.IO.Path]::GetExtension($isoUrl).ToLower()
if ($extension -ne ".iso") {
Write-Host "Warning: The file does not have an .iso extension. It may not be a valid Windows installation image." -ForegroundColor Yellow
$continue = Read-Host "Do you want to continue anyway? (y/n)"
if ($continue -ne 'y' -and $continue -ne 'Y') {
Write-Host "Operation cancelled by user."
exit 0
}
}
# Verify file size (ISO should be at least 3GB)
$fileInfo = Get-Item $isoUrl
$fileSizeMB = [math]::Round($fileInfo.Length / 1MB, 2)
if ($fileSizeMB -lt 3000) {
Write-Host "Warning: The ISO file is only $fileSizeMB MB in size, which is unusually small for a Windows 11 ISO." -ForegroundColor Yellow
Write-Host "A typical Windows 11 ISO is 4-6 GB in size." -ForegroundColor Yellow
$continue = Read-Host "Do you want to continue anyway? (y/n)"
if ($continue -ne 'y' -and $continue -ne 'Y') {
Write-Host "Operation cancelled by user."
exit 0
}
}
# Copy the file with progress indication for large files
Write-Host "Copying ISO file to working location..."
try {
Copy-Item -Path $isoUrl -Destination $isoPath -Force
if (-not (Test-Path $isoPath)) {
throw "Failed to copy ISO file to destination"
}
Write-Host "ISO file copied successfully."
}
catch {
Write-Error "Failed to copy ISO file: $_"
exit 1
}
$isLocalFile = $true
} else {
# Validate the URL before attempting to download
Write-Host "Validating ISO download URL: $isoUrl"
if (-not (Test-UrlIsValid -Url $isoUrl)) {
Write-Error "The specified URL does not appear to be valid or accessible."
Write-Host "Please check the URL and ensure it points to a valid Windows 11 ISO file." -ForegroundColor Yellow
exit 1
}
Write-Host "URL validation successful. Proceeding with download..." -ForegroundColor Green
$isLocalFile = $false
}
# Download ISO if needed
if (-not $isLocalFile) {
Write-Host "Downloading Windows 11 ISO..." -ForegroundColor Cyan
Write-Host "This may take some time depending on your internet connection speed." -ForegroundColor Cyan
Write-Host "Download progress will be displayed..." -ForegroundColor Cyan
try {
# Create a progress-tracking download function
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("User-Agent", "Mozilla/5.0 Windows PowerShell Script")
# Register events for download progress tracking
$eventData = @{}
# Define the handler for DownloadProgressChanged
$ProgressChanged = {
$percent = $eventArgs.ProgressPercentage
$totalBytes = $eventArgs.TotalBytesToReceive
$receivedBytes = $eventArgs.BytesReceived
# Calculate download speed
$currentTime = Get-Date
if (-not $eventData.LastTime) {
$eventData.LastTime = $currentTime
$eventData.LastBytes = 0
}
$timeDiff = ($currentTime - $eventData.LastTime).TotalSeconds
if ($timeDiff -ge 1) {
$byteDiff = $receivedBytes - $eventData.LastBytes
$speedMBps = [math]::Round(($byteDiff / $timeDiff) / 1MB, 2)
# Calculate estimated time remaining
$remainingBytes = $totalBytes - $receivedBytes
$estimatedSeconds = 0
if ($byteDiff -gt 0) {
$estimatedSeconds = [math]::Round($remainingBytes / ($byteDiff / $timeDiff))
}
# Format as hours:minutes:seconds
$estimatedTime = [TimeSpan]::FromSeconds($estimatedSeconds)
$estimatedTimeStr = "{0:hh\:mm\:ss}" -f $estimatedTime
# Convert total size to MB or GB for display
if ($totalBytes -ge 1GB) {
$totalSize = [math]::Round($totalBytes / 1GB, 2)
$downloadedSize = [math]::Round($receivedBytes / 1GB, 2)
$sizeUnit = "GB"
} else {
$totalSize = [math]::Round($totalBytes / 1MB, 2)
$downloadedSize = [math]::Round($receivedBytes / 1MB, 2)
$sizeUnit = "MB"
}
Write-Progress -Activity "Downloading Windows 11 ISO" `
-Status "$percent% Complete - $downloadedSize $sizeUnit of $totalSize $sizeUnit - $speedMBps MB/s" `
-PercentComplete $percent `
-CurrentOperation "Estimated time remaining: $estimatedTimeStr"
# Update for next calculation
$eventData.LastTime = $currentTime
$eventData.LastBytes = $receivedBytes
}
}
# Define the handler for DownloadFileCompleted
$Completed = {
Write-Progress -Activity "Downloading Windows 11 ISO" -Completed
$eventData.Clear()
if ($eventArgs.Error -ne $null) {
throw $eventArgs.Error
}
}
# Register the event handlers
$downloadProgressEvent = Register-ObjectEvent -InputObject $webClient -EventName DownloadProgressChanged -Action $ProgressChanged
$downloadCompletedEvent = Register-ObjectEvent -InputObject $webClient -EventName DownloadFileCompleted -Action $Completed
# Start the download
$webClient.DownloadFileAsync((New-Object System.Uri($isoUrl)), $isoPath)
# Wait for download to complete
while ($webClient.IsBusy) {
Start-Sleep -Milliseconds 100
}
# Clean up event handlers
Unregister-Event -SourceIdentifier $downloadProgressEvent.Id
Unregister-Event -SourceIdentifier $downloadCompletedEvent.Id
# Verify the download
if (Test-Path $isoPath) {
$fileInfo = Get-Item $isoPath
$fileSizeMB = [math]::Round($fileInfo.Length / 1MB, 2)
# Check if file size is reasonable for a Windows ISO
if ($fileSizeMB -lt 3000) {
Write-Host "Warning: The downloaded ISO is only $fileSizeMB MB, which is unusually small for a Windows 11 ISO." -ForegroundColor Yellow
Write-Host "This might indicate a partial download or incorrect ISO source." -ForegroundColor Yellow
$continue = Read-Host "Do you want to continue anyway? (y/n)"
if ($continue -ne 'y' -and $continue -ne 'Y') {
Write-Host "Operation cancelled by user."
exit 0
}
} else {
Write-Host "ISO downloaded successfully ($fileSizeMB MB)." -ForegroundColor Green
}
} else {
throw "ISO download failed: File not found after download"
}
} catch {
Write-Error "Failed to download the ISO: $_"
exit 1
} finally {
# Ensure WebClient is disposed
if ($webClient) {
$webClient.Dispose()
}
}
} else {
Write-Host "ISO file ready: $isoPath" -ForegroundColor Green
}
# Create a working directory for extracted ISO content
$extractDir = $WORKING_DIR
if (Test-Path $extractDir) {
# Clean any existing directory to avoid conflicts
Write-Host "Cleaning existing working directory..."
Remove-Item -Path "$extractDir\*" -Recurse -Force -ErrorAction SilentlyContinue
} else {
# Create new directory
New-Item -Path $extractDir -ItemType Directory -Force | Out-Null
}
# Check for 7-Zip installation
$7zipPath = "C:\Program Files\7-Zip\7z.exe"
if (-not (Test-Path $7zipPath)) {
# Try common alternative path for x86 on x64 systems
$7zipPath = "C:\Program Files (x86)\7-Zip\7z.exe"
if (-not (Test-Path $7zipPath)) {
Write-Host "7-Zip not found. Attempting to download and install it..."
# Download and install 7-Zip using dynamic method to get latest version
try {
# Settings
$downloadPage = "https://www.7-zip.org/download.html"
$downloadPath = "C:\Windows\Temp\7z.msi"
# Download page content
$webClient = New-Object System.Net.WebClient
$htmlContent = $webClient.DownloadString($downloadPage)
# Extract latest x64 MSI link from the current version section
$latestSection = $htmlContent -split '<P><B>Download 7-Zip' | Select-Object -Index 1
# Handle both 32-bit and 64-bit architectures
if ([Environment]::Is64BitOperatingSystem) {
$archPattern = '-x64\.msi'
} else {
$archPattern = '\.msi"'
}
$msiRelativePath = ($latestSection | Select-String -Pattern "href=`"(a/7z\d+.*?$($archPattern))" -AllMatches).Matches[0].Groups[1].Value
# Construct full download URL
$downloadUrl = "https://www.7-zip.org/$msiRelativePath"
Write-Host "Downloading 7-Zip from $downloadUrl"
# Download and install
$webClient.DownloadFile($downloadUrl, $downloadPath)
Start-Process msiexec.exe -ArgumentList "/i `"$downloadPath`" /quiet /norestart" -Wait
# Verify installation
if (-not (Test-Path "C:\Program Files\7-Zip\7z.exe")) {
throw "Failed to install 7-Zip"
}
$7zipPath = "C:\Program Files\7-Zip\7z.exe"
} catch {
Write-Error "Failed to install 7-Zip: $_"
Write-Error "Please install 7-Zip manually and try again."
exit 1
}
}
}
# Extract ISO using 7-Zip
Write-Host "Extracting ISO using 7-Zip (this may take 5-10 minutes)..." -ForegroundColor Cyan
Write-Host "Please be patient while the ISO contents are extracted..." -ForegroundColor Cyan
try {
# Use Start-Process with redirected error streams to capture output without displaying it
$processInfo = New-Object System.Diagnostics.ProcessStartInfo
$processInfo.FileName = $7zipPath
$processInfo.Arguments = "x -y -o`"$extractDir`" `"$isoPath`""
$processInfo.RedirectStandardError = $true
$processInfo.RedirectStandardOutput = $true
$processInfo.UseShellExecute = $false
$processInfo.CreateNoWindow = $true
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $processInfo
$process.Start() | Out-Null
# Display a simple spinner to show progress
$spinner = @('|', '/', '-', '\')
$spinnerPos = 0
$startTime = Get-Date
Write-Host " " -NoNewline
while (-not $process.HasExited) {
Write-Host "`r $($spinner[$spinnerPos]) Extracting... [$(([TimeSpan]::FromSeconds((Get-Date).Subtract($startTime).TotalSeconds)).ToString("hh\:mm\:ss"))]" -NoNewline
$spinnerPos = ($spinnerPos + 1) % 4
Start-Sleep -Milliseconds 200
}
Write-Host "`r ✓ Extraction complete [$(([TimeSpan]::FromSeconds((Get-Date).Subtract($startTime).TotalSeconds)).ToString("hh\:mm\:ss"))] " -ForegroundColor Green
# Get the output without displaying it
$standardOutput = $process.StandardOutput.ReadToEnd()
$standardError = $process.StandardError.ReadToEnd()
# Check the exit code
if ($process.ExitCode -ne 0) {
# Format a user-friendly error message without dumping everything
Write-Host "ERROR: 7-Zip extraction failed with exit code $($process.ExitCode)" -ForegroundColor Red
Write-Host "The ISO file may be corrupted or incompatible." -ForegroundColor Yellow
# Show minimal error information
if (-not [string]::IsNullOrEmpty($standardError)) {
$errorLines = $standardError -split "`n"
$relevantError = ($errorLines | Where-Object { $_ -match "ERROR:" } | Select-Object -First 1)
if ($relevantError) {
Write-Host "Error details: $relevantError" -ForegroundColor Yellow
}
}
exit 1
}
# Verify extraction succeeded
$setupPath = "$extractDir\setup.exe"
if (-not (Test-Path $setupPath)) {
Write-Host "ERROR: Extraction completed but setup.exe was not found." -ForegroundColor Red
Write-Host "This suggests the ISO does not contain a valid Windows installation." -ForegroundColor Yellow
Write-Host "Please verify you are using a proper Windows 11 installation ISO." -ForegroundColor Yellow
exit 1
}
Write-Host "ISO extracted successfully to $extractDir" -ForegroundColor Green
# Create zero-byte appraiserres.dll to bypass TPM check
Write-Host "Creating TPM check bypass..."
$appraiserdllPath = "$extractDir\sources\appraiserres.dll"
if (Test-Path $appraiserdllPath) {
# Make a backup just in case
Copy-Item -Path $appraiserdllPath -Destination "$appraiserdllPath.bak" -Force
# Replace with zero-byte file
Set-Content -Path $appraiserdllPath -Value "" -Force
} else {
# Create new zero-byte file if it doesn't exist
New-Item -Path $appraiserdllPath -ItemType File -Force | Out-Null
}
# Create EI.cfg to avoid product key prompts
$eiCfgPath = "$extractDir\sources\EI.cfg"
Set-Content -Path $eiCfgPath -Value "[Channel]`n_Default" -Force
# Create SetupConfig.ini
$setupConfigPath = "$extractDir\sources\SetupConfig.ini"
$setupConfig = @"
[BeginSetupMode]
SkipPrediagler=1
DeviceEnumeration=1
DiscoverSystemPartition=1
[SetupConfig]
ScratchDir=$env:SystemDrive\`$WINDOWS.~BT
ScratchSpace=12000
PreinstallKitSpace=8000
"@
Set-Content -Path $setupConfigPath -Value $setupConfig -Force
# Run setup.exe with appropriate arguments and stronger compatibility bypass options
Write-Host "Starting Windows 11 upgrade from extracted ISO with maximum compatibility overrides..."
# Create custom answer file to force upgrade
$answerFilePath = "$extractDir\unattend.xml"
$answerFileContent = @"
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="windowsPE">
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<ComplianceCheck>
<DisplayReport>Never</DisplayReport>
</ComplianceCheck>
<Diagnostics>
<OptIn>false</OptIn>
</Diagnostics>
<DynamicUpdate>
<Enable>true</Enable>
<WillShowUI>OnError</WillShowUI>
</DynamicUpdate>
<ImageInstall>
<OSImage>
<InstallFrom>
<MetaData>
<Key>/IMAGE/INDEX</Key>
<Value>1</Value>
</MetaData>
</InstallFrom>
<InstallTo>
<DiskID>0</DiskID>
<PartitionID>1</PartitionID>
</InstallTo>
<WillShowUI>OnError</WillShowUI>
<InstallToAvailablePartition>true</InstallToAvailablePartition>
</OSImage>
</ImageInstall>
<UserData>
<AcceptEula>true</AcceptEula>
</UserData>
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /d 1 /t reg_dword /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /d 1 /t reg_dword /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassRAMCheck /d 1 /t reg_dword /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassCPUCheck /d 1 /t reg_dword /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassStorageCheck /d 1 /t reg_dword /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>6</Order>
<Path>reg add HKLM\SYSTEM\Setup\MoSetup /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
</unattend>
"@
Set-Content -Path $answerFilePath -Value $answerFileContent -Force
Write-Host "Created custom unattend.xml file for compatibility bypass"
# Try the alternate 'Server' product trick - update setup files
Write-Host "Applying 'Server' product trick to bypass hardware checks..."
try {
$setupConfigDatPath = "$extractDir\sources\setupconfig.dat"
if (Test-Path $setupConfigDatPath) {
$content = Get-Content -Path $setupConfigDatPath -Encoding Byte
$clientPattern = [System.Text.Encoding]::Unicode.GetBytes("Client")
$serverPattern = [System.Text.Encoding]::Unicode.GetBytes("Server")
$found = $false
for ($i = 0; $i -lt $content.Length - $clientPattern.Length; $i++) {
$matched = $true
for ($j = 0; $j -lt $clientPattern.Length; $j++) {
if ($content[$i + $j] -ne $clientPattern[$j]) {
$matched = $false
break
}
}
if ($matched) {
$found = $true
for ($j = 0; $j -lt $serverPattern.Length; $j++) {
$content[$i + $j] = $serverPattern[$j]
}
}
}
if ($found) {
[System.IO.File]::WriteAllBytes($setupConfigDatPath, $content)
Write-Host "Successfully modified setupconfig.dat to use Server edition bypass"
}
}
} catch {
Write-Host "Warning: Could not modify setupconfig.dat: $_"
}
# Setup command line arguments
$arguments = @(
"/auto", "upgrade",
"/quiet",
"/compat", "ignorewarning",
"/migratedrivers", "all",
"/showoobe", "none",
"/telemetry", "disable",
"/dynamicupdate", "enable",
"/eula", "accept",
"/unattend:$answerFilePath",
"/product", "server", # Add server product parameter to bypass hardware checks
"/pkey", "VK7JG-NPHTM-C97JM-9MPGT-3V66T" # Generic Windows 11 Pro key
)
# Add /noreboot switch if automatic reboots are disabled
if (-not $ALLOW_AUTOMATIC_REBOOT) {
$arguments += "/noreboot"
Write-Host "Automatic reboots are disabled. The system will need to be manually rebooted to complete the upgrade."
} else {
Write-Host "Automatic reboots are enabled. The system will reboot automatically when needed."
}
# Create a log file to track progress
$logFile = $LOG_FILE
Set-Content -Path $logFile -Value "Windows 11 Upgrade started at $(Get-Date)`r`n" -Force
# Function to log progress
function Write-ProgressLog {
param(
[string]$Message
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "[$timestamp] $Message"
Write-Host $logMessage
Add-Content -Path $logFile -Value $logMessage
}
# Function to check if Windows Setup is running
function Is-SetupRunning {
$setupProcesses = @(
"SetupHost", # This is the critical process for actual Windows upgrade execution
"setupprep",
"setup",
"Windows10UpgraderApp"
)
foreach ($proc in $setupProcesses) {
$running = Get-Process -Name $proc -ErrorAction SilentlyContinue
if ($running) {
if ($proc -eq "SetupHost") {
Write-ProgressLog "CRITICAL SUCCESS: SetupHost.exe is running! This confirms the upgrade is properly underway."
return @{Success = $true; Critical = $true}
}
return @{Success = $true; Critical = $false}
}
}
return @{Success = $false; Critical = $false}
}
# Function to wait for SetupHost.exe to appear (the definitive sign that upgrade is working)
function Wait-ForSetupHost {
param (
[int]$TimeoutSeconds = 300, # Wait up to 5 minutes by default
[int]$CheckIntervalSeconds = 5
)
Write-ProgressLog "Waiting for SetupHost.exe to start (the critical process for Windows upgrades)..."
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$timeoutMs = $TimeoutSeconds * 1000
while ($stopwatch.ElapsedMilliseconds -lt $timeoutMs) {
$setupHost = Get-Process -Name "SetupHost" -ErrorAction SilentlyContinue
if ($setupHost) {
$stopwatch.Stop()
Write-ProgressLog "SUCCESS: SetupHost.exe started after $([math]::Round($stopwatch.ElapsedMilliseconds / 1000)) seconds."
Write-ProgressLog "SetupHost.exe PID: $($setupHost.Id), Started at: $(Get-Date)"
return $true
}
# Check for setupprep - it should start first and launch SetupHost
$setupPrep = Get-Process -Name "setupprep" -ErrorAction SilentlyContinue
if ($setupPrep) {
Write-ProgressLog "setupprep.exe is running (PID: $($setupPrep.Id)). Waiting for it to launch SetupHost.exe..."
}
# Sleep before checking again
Start-Sleep -Seconds $CheckIntervalSeconds
}
$stopwatch.Stop()
Write-ProgressLog "WARNING: SetupHost.exe did not start within $TimeoutSeconds seconds."
return $false
}
Write-ProgressLog "Starting Windows 11 upgrade from extracted ISO..."
Write-ProgressLog "To monitor progress, check the log file at: $logFile"
Write-ProgressLog "You can also look for these processes: SetupHost.exe, setupprep.exe, setup.exe"
# Start setup without waiting
$arguments += "/PostOOBE", "$extractDir\PostInstall.cmd"
# Create a post-install script to log completion
$postInstallScript = @"
@echo off
echo Windows 11 Upgrade completed at %DATE% %TIME% > C:\Win11_Upgrade_Completed.log
"@
Set-Content -Path "$extractDir\PostInstall.cmd" -Value $postInstallScript -Force
# Start the setup process
Write-ProgressLog "Launching setup.exe with arguments: $($arguments -join ' ')"
$process = Start-Process -FilePath $setupPath -ArgumentList $arguments -PassThru -NoNewWindow
# Wait briefly to see if initial processes start
Start-Sleep -Seconds 5
# Check if setup is running and log process ID
$setupStatus = Is-SetupRunning
if ($setupStatus.Success) {
$setupProcesses = Get-Process | Where-Object { $_.Name -match "setup|SetupHost" }
foreach ($proc in $setupProcesses) {
Write-ProgressLog "Setup process running: $($proc.Name) (PID: $($proc.Id))"
}
if ($setupStatus.Critical) {
Write-ProgressLog "VERIFIED: SetupHost.exe is running! The upgrade is confirmed to be properly underway."
} else {
# SetupHost is not yet running - wait for it as it's the critical indicator
Write-ProgressLog "Initial setup processes started, but waiting for SetupHost.exe (the critical component)..."
# Wait for SetupHost to appear - this is the definitive test
$setupHostStarted = Wait-ForSetupHost -TimeoutSeconds 600 # Wait up to 10 minutes
if ($setupHostStarted) {
Write-ProgressLog "UPGRADE CONFIRMED: SetupHost.exe is running. The Windows 11 upgrade is now definitely underway."
Write-ProgressLog "This is the critical process that indicates the actual upgrade is proceeding correctly."
} else {
Write-ProgressLog "WARNING: SetupHost.exe did not start within the expected timeframe."
Write-ProgressLog "The upgrade may still proceed, but you should monitor it carefully."
Write-ProgressLog "If the upgrade does not complete, you may need to run the script again."
}
}
Write-ProgressLog "Setup initiated. The upgrade is now running in the background."
Write-ProgressLog "To check if it's running, use Task Manager to look for SetupHost.exe."
} else {
Write-ProgressLog "Warning: Setup may not have started correctly."
Write-ProgressLog "Checking exit code: $($process.ExitCode)"
# Try alternative approach - direct setupprep.exe execution with Server trick
Write-ProgressLog "Trying alternative approach with setupprep.exe and Server trick..."
$setupPrepPath = "$extractDir\sources\setupprep.exe"
if (Test-Path $setupPrepPath) {
# Prepare $WINDOWS.~BT directory
$btDir = "$env:SystemDrive\`$WINDOWS.~BT\Sources"
if (-not (Test-Path $btDir)) {
New-Item -Path $btDir -ItemType Directory -Force | Out-Null
}
# Copy critical files to ensure Windows.~BT has what it needs
Write-ProgressLog "Copying setup files to Windows.~BT directory..."
Copy-Item -Path "$extractDir\sources\*" -Destination $btDir -Force -Recurse
# Create zero-byte appraiserres.dll in Windows.~BT
Set-Content -Path "$btDir\appraiserres.dll" -Value "" -Force
# Add additional bypass files
Set-Content -Path "$btDir\Skip.cmd" -Value @"
@echo off
reg add HKLM\SYSTEM\Setup\MoSetup /f /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword
reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassTPMCheck /d 1 /t reg_dword
reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassSecureBootCheck /d 1 /t reg_dword
reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassRAMCheck /d 1 /t reg_dword
reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassStorageCheck /d 1 /t reg_dword
reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassCPUCheck /d 1 /t reg_dword
reg add HKLM\SYSTEM\Setup /f /v BypassComponentCheck /d 1 /t reg_dword
"@ -Force
# Modify the EditionID to ensure compatibility
$regScript = @"
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion]
"EditionID_undo"="Professional"
"EditionID"="Professional"
"ProductName"="Windows 11 Pro"
"@
Set-Content -Path "$btDir\edition.reg" -Value $regScript -Force
# Create batch file to run registry changes and launch setup
$setupBatchPath = "$btDir\RunSetup.cmd"
$setupCommand = "setupprep.exe /product server /auto upgrade /quiet /compat ignorewarning /migratedrivers all /dynamicupdate enable /eula accept"
# Add noreboot switch if automatic reboots are disabled
if (-not $ALLOW_AUTOMATIC_REBOOT) {
$setupCommand += " /noreboot"
}
$setupBatch = @"
@echo off
cd /d "%~dp0"
call Skip.cmd
regedit /s edition.reg
$setupCommand
"@
Set-Content -Path $setupBatchPath -Value $setupBatch -Force
# Run the batch file to execute setup with all bypasses
Write-ProgressLog "Launching setup with all compatibility bypasses..."
Start-Process -FilePath "cmd.exe" -ArgumentList "/c $setupBatchPath" -PassThru -NoNewWindow
# Wait briefly to check if it started
Start-Sleep -Seconds 5
# Check again if setup is running
$setupStatus = Is-SetupRunning
if ($setupStatus.Success) {
$setupProcesses = Get-Process | Where-Object { $_.Name -match "setup|SetupHost" }
foreach ($proc in $setupProcesses) {
Write-ProgressLog "Setup process running: $($proc.Name) (PID: $($proc.Id))"
}
if ($setupStatus.Critical) {
Write-ProgressLog "VERIFIED: SetupHost.exe is running via fallback method! The upgrade is confirmed to be properly underway."
} else {
# SetupHost is not yet running - wait for it as it's the critical indicator
Write-ProgressLog "Initial setup processes started via fallback method, waiting for SetupHost.exe..."
# Wait for SetupHost to appear - this is the definitive test
$setupHostStarted = Wait-ForSetupHost -TimeoutSeconds 600 # Wait up to 10 minutes
if ($setupHostStarted) {
Write-ProgressLog "UPGRADE CONFIRMED: SetupHost.exe is running. The Windows 11 upgrade is now definitely underway."
} else {
Write-ProgressLog "WARNING: SetupHost.exe did not start within the expected timeframe."
Write-ProgressLog "The upgrade may still proceed, but monitoring is recommended."
}
}
Write-ProgressLog "Setup initiated via fallback method. The upgrade is now running in the background."
} else {
Write-ProgressLog "WARNING: Both setup methods failed to start the upgrade process."
Write-ProgressLog "Please check the logs and consider running the script again."
}
}
# Create a simple monitor script that only logs progress
$monitorScript = @"
@echo off
echo Windows 11 upgrade monitor started at %DATE% %TIME% > "%MONITOR_LOG%"
:check
echo ------------------------------------------------ >> "%MONITOR_LOG%"
echo Checking processes at %DATE% %TIME% >> "%MONITOR_LOG%"
tasklist /fi "imagename eq setuphost.exe" >> "%MONITOR_LOG%"
tasklist /fi "imagename eq setupprep.exe" >> "%MONITOR_LOG%"
tasklist /fi "imagename eq setup.exe" >> "%MONITOR_LOG%"
REM Check if RebootRequired registry exists (for logging only)
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" > nul 2>&1
if %ERRORLEVEL% EQU 0 (
echo Reboot Required registry key found! Windows should reboot automatically. >> "%MONITOR_LOG%"
)
REM Check if installation phase registry indicates readiness (for logging only)
reg query "HKLM\SYSTEM\Setup" /v SystemSetupInProgress > nul 2>&1
if %ERRORLEVEL% EQU 0 (
for /f "tokens=3" %%a in ('reg query "HKLM\SYSTEM\Setup" /v SystemSetupInProgress ^| find "SystemSetupInProgress"') do set SETUP_PROGRESS=%%a
echo SystemSetupInProgress value: !SETUP_PROGRESS! >> "%MONITOR_LOG%"
)
REM Log recent activity in setup logs
echo Recent setup logs: >> "%MONITOR_LOG%"
dir /a-d /od C:\$WINDOWS.~BT\Sources\Panther\*.log >> "%MONITOR_LOG%" 2>&1
REM Log memory info to monitor system health
echo Memory status: >> "%MONITOR_LOG%"
systeminfo | find "Physical Memory" >> "%MONITOR_LOG%"
echo. >> "%MONITOR_LOG%"
timeout /t 300 > nul
goto check
"@
Set-Content -Path "$extractDir\MonitorSetup.cmd" -Value $monitorScript -Force
# Start the monitor script in a hidden window
Start-Process -FilePath "cmd.exe" -ArgumentList "/c $extractDir\MonitorSetup.cmd" -WindowStyle Hidden
}
# Clean up - delete the downloaded ISO but keep extracted files for debugging
Remove-Item -Path $isoPath -Force -ErrorAction SilentlyContinue
} catch {
# Extract only the essential error message without the full stack trace
$errorMessage = $_.Exception.Message
if ($errorMessage.Length -gt 150) {
$errorMessage = $errorMessage.Substring(0, 150) + "..."
}
# Create a clean, user-friendly error message
$detailedMessage = "The Windows 11 upgrade process encountered an issue and could not continue.`nTry again or check the log file at $logFile for more details."
# Try to clean up
try {
Remove-Item -Path $isoPath -Force -ErrorAction SilentlyContinue
} catch {
# Ignore cleanup errors
}
# Show clean error message
Write-Host "ERROR: Windows 11 upgrade process failed." -ForegroundColor Red
Write-Host "The Windows 11 upgrade process encountered an issue and could not continue." -ForegroundColor Yellow
Write-Host "Try again or check the log file at $logFile for more details." -ForegroundColor Yellow
exit 1
}
# Final progress information and verification
if ($ALLOW_AUTOMATIC_REBOOT) {
Write-ProgressLog "Windows 11 upgrade process initiated. The system will reboot automatically when the upgrade is complete."
} else {
Write-ProgressLog "Windows 11 upgrade process initiated. Manual reboot will be required when the upgrade preparation is complete."
}
Write-ProgressLog ""
Write-ProgressLog "To verify the upgrade is running, check for these files:"
Write-ProgressLog "- $logFile - Contains detailed progress information"
Write-ProgressLog "- $MONITOR_LOG - Contains periodic process checks every 5 minutes"
Write-ProgressLog "- C:\Win11_Upgrade_Completed.log - Will be created when upgrade completes"
Write-ProgressLog ""
Write-ProgressLog "You should also see one or more of these processes in Task Manager:"
Write-ProgressLog "- SetupHost.exe - Main upgrade process"
Write-ProgressLog "- setupprep.exe - Preparation process"
Write-ProgressLog "- setup.exe - Initial setup launcher"
Write-ProgressLog ""
Write-ProgressLog "Process monitoring is active but no automatic intervention will occur."
Write-ProgressLog "Windows Setup will handle the reboot process organically when ready."
# One final check to make absolutely sure SetupHost is running
Write-ProgressLog "Performing final verification to ensure SetupHost.exe is running..."
Start-Sleep -Seconds 15
$setupHost = Get-Process -Name "SetupHost" -ErrorAction SilentlyContinue
if ($setupHost) {
Write-ProgressLog "FINAL VERIFICATION PASSED: SetupHost.exe is running (PID: $($setupHost.Id))."
Write-ProgressLog "The Windows 11 upgrade is definitely underway and proceeding properly."
Write-ProgressLog "This is the CRITICAL process that confirms the upgrade will complete successfully."
# Log all running setup processes for completeness
$setupProcesses = Get-Process | Where-Object { $_.Name -match "setup|SetupHost" }
Write-ProgressLog "All running setup processes:"
foreach ($proc in $setupProcesses) {
Write-ProgressLog "- $($proc.Name) (PID: $($proc.Id))"
}
Write-ProgressLog "UPGRADE STATUS: SUCCESS - The script has successfully initiated the Windows 11 upgrade."
} else {
# SetupHost is still not running - check for any setup processes
$setupStatus = Is-SetupRunning
if ($setupStatus.Success) {
Write-ProgressLog "WARNING: Setup processes are running, but SetupHost.exe has not started yet."
Write-ProgressLog "The upgrade may still proceed, but it's recommended to monitor the process."
Write-ProgressLog "If needed, check the C:\$WINDOWS.~BT\Sources\Panther directory for logs."
# One last attempt to wait for SetupHost
Write-ProgressLog "Making final attempt to wait for SetupHost.exe to start..."
$finalAttempt = Wait-ForSetupHost -TimeoutSeconds 300 # Wait 5 more minutes
if ($finalAttempt) {
Write-ProgressLog "SUCCESS: SetupHost.exe has finally started. The upgrade is now properly underway."
} else {
Write-ProgressLog "CAUTION: SetupHost.exe still not detected. The upgrade process may be abnormal."
Write-ProgressLog "Please monitor the system to ensure the upgrade completes successfully."
}
} else {
Write-ProgressLog "CRITICAL WARNING: No setup processes are running. The upgrade has likely failed to start."
Write-ProgressLog "Check C:\$WINDOWS.~BT\Sources\Panther directory for setupact.log and setuperr.log files"
Write-ProgressLog "You may need to run the script again or try a different approach."
}
}

90
README.md Normal file
View File

@@ -0,0 +1,90 @@
# Silent Windows 11 Upgrade Script
This PowerShell script enables silent in-place upgrades to Windows 11, specifically designed for systems that fail compatibility checks when attempting major version upgrades through Windows Update.
## Purpose
Windows 11 systems on older major versions (21H2, 22H2) often cannot upgrade to newer versions (23H2, 24H2) via Windows Update due to failing compatibility checks. This script bypasses these limitations by:
- Bypassing TPM, CPU, and other hardware compatibility checks
- Enabling in-place upgrades even on "unsupported" hardware
- Providing a completely silent, no-interaction upgrade process
- Automatically handling all aspects of the upgrade, including reboots
## Features
- **Bypasses Hardware Requirements**: Overcomes TPM, CPU, RAM, SecureBoot and other compatibility blocks
- **Automated ISO Handling**: Downloads or uses local ISO files (configurable)
- **Dependency Management**: Automatically installs 7-Zip if not present
- **Silent Operation**: Runs completely in the background with no user interaction
- **Configurable Reboots**: Supports automatic or manual reboot options
- **Detailed Logging**: Provides comprehensive monitoring of the upgrade process
- **Cross-Version Compatibility**: Works for upgrading from Windows 10 to 11, or between Windows 11 versions
## Usage
1. **Download**: Clone or download this script to your system
2. **Configure**: Edit the parameters at the top of the script:
```powershell
# ISO source (direct URL, local file, or network share)
$WIN11_ISO_SOURCE = "path-to-iso-or-url"
# Reboot behavior
$ALLOW_AUTOMATIC_REBOOT = $true # Set to $false to prevent automatic reboots
```
3. **Execute**: Run the script with administrative privileges
```
powershell.exe -ExecutionPolicy Bypass -File "C:\path\to\DirectWindowsUpgrade.ps1"
```
## Process Details
- The script extracts the Windows 11 ISO using 7-Zip
- Registry keys are set to bypass hardware compatibility checks
- Setup files are prepared with appropriate parameters
- The upgrade process runs completely silently
- By default, the system will reboot automatically when needed
- Total upgrade process takes approximately 1.5 hours to complete
## Requirements
- Windows 10 or Windows 11 system
- Administrative privileges
- Internet access (if using download URL) or access to Windows 11 ISO
- 10GB+ free space for the upgrade process
## ISO Source
For best results, use the business editions of Windows 11 with this script. You can obtain ISOs from:
- Official Microsoft sources
- [MassGrave Genuine Windows ISOs](https://massgrave.dev/genuine-installation-media.html)
Make sure to use an ISO that contains the Windows 11 version you want to upgrade to (e.g., 23H2, 24H2).
## When to Use This Script
- When Windows Update fails to offer major Windows 11 version upgrades
- When systems have "unsupported" hardware that blocks updates
- When you need to perform silent, unattended upgrades
- For bulk upgrades across multiple systems with similar hardware
## Logs and Monitoring
The script generates several log files to help monitor progress:
- `C:\Win11_Upgrade_Progress.log` - Main progress log
- `C:\Win11_Monitor.log` - Process monitoring log
- `C:\Win11_Upgrade_Completed.log` - Created upon successful completion
## Customization
All configurable parameters are at the top of the script:
- `$WIN11_ISO_SOURCE` - Source location for Windows 11 ISO
- `$WORKING_DIR` - Main working directory
- `$TEMP_DIR` - Temporary directory for downloads
- `$LOG_FILE` - Main log file path
- `$MONITOR_LOG` - Process monitor log path
- `$ALLOW_AUTOMATIC_REBOOT` - Enable/disable automatic reboots
## Attribution
This script combines techniques from multiple sources, including AveYo's MediaCreationTool project, for maximum compatibility with different Windows 11 versions and hardware configurations.