da64u

Windows 11 Upgrade

May 13th, 2025
8
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.52 KB | None | 0 0
  1. # Direct Windows 11 Upgrade - No GUI
  2. #
  3. # This script performs a silent in-place upgrade to Windows 11, supporting:
  4. # - Upgrading from Windows 10 to Windows 11
  5. # - Upgrading from older Windows 11 versions to newer versions (e.g., 21H2 to 22H2)
  6. # - Completely silent operation with no user interaction required
  7. # - Bypassing TPM, CPU, and other hardware compatibility checks
  8. #
  9. # PROCESS DETAILS:
  10. # - The script will install 7-Zip if not already present (required to extract ISO contents)
  11. # - Total upgrade process takes approximately 1.5 hours to complete
  12. # - By default, the system will automatically reboot when necessary (configurable)
  13. # - No user intervention is required at any point in the process
  14. #
  15. # USAGE NOTES:
  16. # 1. Edit the configuration section below to specify your Windows 11 ISO source
  17. # 2. Make sure to use an ISO containing the Windows 11 version you want to upgrade to
  18. # 3. Recommended ISO source: https://massgrave.dev/genuine-installation-media.html
  19. # 4. Run this script with administrative privileges
  20.  
  21. #######################################################################
  22. # CONFIGURATION - MODIFY THESE SETTINGS AS NEEDED
  23. #######################################################################
  24.  
  25. # Specify the Windows 11 ISO source - MODIFY THIS FOR YOUR ENVIRONMENT
  26. # Options:
  27. # 1. Direct download URL (default)
  28. # 2. Local file path (e.g., "C:\Path\To\Windows11.iso")
  29. # 3. Network share (e.g., "\\server\share\Windows11.iso")
  30. #
  31. # IMPORTANT: The ISO must contain the Windows 11 version you want to upgrade to.
  32. # Business editions are recommended as they have fewer issues with silent upgrades.
  33. # You can download official ISOs from: https://massgrave.dev/genuine-installation-media.html
  34. $WIN11_ISO_SOURCE = "c:\temp\Win11_24H2_English_x64.iso"
  35.  
  36. # WORKING DIRECTORIES - you can modify these if needed
  37. $WORKING_DIR = "C:\Win11Upgrade" # Main working directory
  38. $TEMP_DIR = "C:\Windows\Temp" # Temporary directory
  39. $LOG_FILE = "C:\Win11_Upgrade_Progress.log" # Main log file
  40. $MONITOR_LOG = "C:\Win11_Monitor.log" # Process monitor log file
  41.  
  42. # BEHAVIOR SETTINGS
  43. $BYPASS_CONFIRMATION = $true # Set to $true to skip all confirmation prompts
  44. $ALLOW_AUTOMATIC_REBOOT = $false # Set to $false to prevent automatic reboots
  45.  
  46. #######################################################################
  47. # SCRIPT BEGINS HERE - DO NOT MODIFY BELOW THIS LINE UNLESS NECESSARY
  48. #######################################################################
  49.  
  50. # Ensure running as admin
  51. if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
  52. Write-Host "ERROR: This script requires administrator privileges." -ForegroundColor Red
  53. Write-Host "Please restart the script with administrator rights." -ForegroundColor Yellow
  54. exit 1
  55. }
  56.  
  57. # Use the ISO source defined at the top of the script
  58. $isoUrl = $WIN11_ISO_SOURCE
  59. $isoPath = "$TEMP_DIR\windows11.iso"
  60.  
  61. # Validate the URL or file path before doing anything else
  62. if ($isoUrl -eq "https://replace/this/url/with/your/iso/windows.iso") {
  63. Write-Host "ERROR: You need to replace the placeholder URL in the configuration section." -ForegroundColor Red
  64. Write-Host "Please edit the script and update the `$WIN11_ISO_SOURCE variable with a valid ISO URL or file path." -ForegroundColor Yellow
  65. exit 1
  66. }
  67.  
  68. # Show confirmation prompt
  69. Write-Host "WARNING: You are about to start an automated Windows 11 upgrade process." -ForegroundColor Yellow
  70. Write-Host ""
  71. Write-Host "The following will occur if you proceed:"
  72. Write-Host "- 7-Zip will be installed (if not already present)"
  73. Write-Host "- System settings will be modified"
  74. Write-Host "- Your PC will reboot when the installation is ready"
  75. Write-Host "- The entire process takes approximately 1.5 hours"
  76. Write-Host ""
  77. Write-Host "IMPORTANT NOTES:" -ForegroundColor Cyan
  78. Write-Host "- Please be patient during the upgrade process"
  79. Write-Host "- As long as SetupHost.exe is running in Task Manager, the upgrade is working"
  80. Write-Host "- The process may appear to stall at times, but this is normal"
  81. Write-Host "- Do not interrupt the process once it has started"
  82. Write-Host ""
  83.  
  84. if (-not $BYPASS_CONFIRMATION) {
  85. $confirmation = Read-Host "Do you want to continue with the Windows 11 upgrade? (y/n)"
  86. if ($confirmation -ne 'y' -and $confirmation -ne 'Y') {
  87. Write-Host "Windows 11 upgrade cancelled by user."
  88. exit 0
  89. }
  90. } else {
  91. Write-Host "Confirmation bypassed. Proceeding with Windows 11 upgrade automatically..." -ForegroundColor Yellow
  92. }
  93.  
  94. # Set aggressive compatibility bypass registry keys
  95. Write-Host "Setting comprehensive compatibility bypass registry keys..."
  96.  
  97. # TPM and basic hardware checks
  98. reg add "HKLM\SYSTEM\Setup\MoSetup" /f /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword
  99. reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassTPMCheck /d 1 /t reg_dword
  100. reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassSecureBootCheck /d 1 /t reg_dword
  101. reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassRAMCheck /d 1 /t reg_dword
  102. reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassStorageCheck /d 1 /t reg_dword
  103. reg add "HKLM\SYSTEM\Setup\LabConfig" /f /v BypassCPUCheck /d 1 /t reg_dword
  104.  
  105. # Safeguard overrides
  106. reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v DisableWUfBSafeguards /d 1 /t reg_dword
  107. reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\UpdatePolicy\Settings" /f /v DisableWUfBSafeguards /d 1 /t reg_dword
  108. reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v DisableSafeguards /d 1 /t reg_dword
  109.  
  110. # Setup compatibility settings
  111. reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreAllWarnings /d 1 /t reg_dword
  112. reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreHWRequirements /d 1 /t reg_dword
  113. reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreApplicationsOnUpgrade /d 1 /t reg_dword
  114. reg add "HKLM\SYSTEM\Setup\UpgradeCompat" /f /v IgnoreAppsOnUpgrade /d 1 /t reg_dword
  115. reg add "HKLM\SYSTEM\Setup\Status\UninstallWindow" /f /v UninstallActive /d 0 /t reg_dword
  116.  
  117. # Disable compatibility checks
  118. reg add "HKLM\SYSTEM\Setup" /f /v BypassCompatibilityCheck /d 1 /t reg_dword
  119.  
  120. # Disable error reporting during upgrade
  121. reg add "HKLM\SOFTWARE\Microsoft\PCHealth\ErrorReporting" /f /v DoReport /d 0 /t reg_dword
  122. reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting" /f /v Disabled /d 1 /t reg_dword
  123.  
  124. # Skip setup compliance checks
  125. reg add "HKLM\SYSTEM\Setup" /f /v BypassComplianceCheck /d 1 /t reg_dword
  126.  
  127. # Allow setup to continue despite errors
  128. reg add "HKLM\SYSTEM\Setup" /f /v AllowNonZeroExitStatus /d 1 /t reg_dword
  129.  
  130. # Disable CEIP during setup
  131. reg add "HKLM\SOFTWARE\Policies\Microsoft\SQMClient\Windows" /f /v CEIPEnable /d 0 /t reg_dword
  132.  
  133. # Force target platform version
  134. reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v TargetReleaseVersion /d 1 /t reg_dword
  135. reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f /v TargetReleaseVersionInfo /d "25H1" /t reg_sz
  136.  
  137. # Function to validate URL - ensures the URL is reachable before download
  138. function Test-UrlIsValid {
  139. param (
  140. [string]$Url
  141. )
  142.  
  143. try {
  144. # Simple HEAD request to check if URL is reachable
  145. $request = [System.Net.WebRequest]::Create($Url)
  146. $request.Method = "HEAD"
  147. $request.Timeout = 15000 # 15 seconds timeout
  148. $request.UserAgent = "Mozilla/5.0 Windows PowerShell Script"
  149.  
  150. # Get the response
  151. $response = $request.GetResponse()
  152.  
  153. # Check if we can access the URL
  154. $success = $response.StatusCode -eq [System.Net.HttpStatusCode]::OK
  155.  
  156. # Show file size if available
  157. $contentLength = $response.Headers["Content-Length"]
  158. if ($contentLength) {
  159. $sizeInMB = [math]::Round([long]$contentLength / 1MB, 2)
  160. if ($sizeInMB -gt 1000) {
  161. Write-Host "File size: $([math]::Round($sizeInMB / 1024, 2)) GB" -ForegroundColor Cyan
  162. } else {
  163. Write-Host "File size: $sizeInMB MB" -ForegroundColor Cyan
  164. }
  165. }
  166.  
  167. # Close the response
  168. $response.Close()
  169. return $success
  170. }
  171. catch {
  172. # Simple error message without details that could cause red dumps
  173. Write-Host "ERROR: Could not access the URL. Please verify it's correct and accessible." -ForegroundColor Red
  174. return $false
  175. }
  176. }
  177.  
  178. # If the ISO source is a local file or network share, copy it to the temp directory
  179. if (Test-Path $isoUrl) {
  180. Write-Host "Using local/network ISO file: $isoUrl"
  181.  
  182. # Verify it's an ISO file
  183. $extension = [System.IO.Path]::GetExtension($isoUrl).ToLower()
  184. if ($extension -ne ".iso") {
  185. Write-Host "Warning: The file does not have an .iso extension. It may not be a valid Windows installation image." -ForegroundColor Yellow
  186. if (-not $BYPASS_CONFIRMATION) {
  187. $continue = Read-Host "Do you want to continue anyway? (y/n)"
  188. if ($continue -ne 'y' -and $continue -ne 'Y') {
  189. Write-Host "Operation cancelled by user."
  190. exit 0
  191. }
  192. } else {
  193. Write-Host "Confirmation bypassed. Continuing despite non-ISO extension..." -ForegroundColor Yellow
  194. }
  195. }
  196.  
  197. # Verify file size (ISO should be at least 3GB)
  198. $fileInfo = Get-Item $isoUrl
  199. $fileSizeMB = [math]::Round($fileInfo.Length / 1MB, 2)
  200. if ($fileSizeMB -lt 3000) {
  201. Write-Host "Warning: The ISO file is only $fileSizeMB MB in size, which is unusually small for a Windows 11 ISO." -ForegroundColor Yellow
  202. Write-Host "A typical Windows 11 ISO is 4-6 GB in size." -ForegroundColor Yellow
  203. if (-not $BYPASS_CONFIRMATION) {
  204. $continue = Read-Host "Do you want to continue anyway? (y/n)"
  205. if ($continue -ne 'y' -and $continue -ne 'Y') {
  206. Write-Host "Operation cancelled by user."
  207. exit 0
  208. }
  209. } else {
  210. Write-Host "Confirmation bypassed. Continuing despite small ISO size..." -ForegroundColor Yellow
  211. }
  212. }
  213.  
  214. # Copy the file with progress indication for large files
  215. Write-Host "Copying ISO file to working location..."
  216. try {
  217. Copy-Item -Path $isoUrl -Destination $isoPath -Force
  218. if (-not (Test-Path $isoPath)) {
  219. throw "Failed to copy ISO file to destination"
  220. }
  221. Write-Host "ISO file copied successfully."
  222. }
  223. catch {
  224. Write-Error "Failed to copy ISO file: $_"
  225. exit 1
  226. }
  227.  
  228. $isLocalFile = $true
  229. } else {
  230. # Validate the URL before attempting to download
  231. Write-Host "Validating ISO download URL: $isoUrl"
  232. if (-not (Test-UrlIsValid -Url $isoUrl)) {
  233. Write-Error "The specified URL does not appear to be valid or accessible."
  234. Write-Host "Please check the URL and ensure it points to a valid Windows 11 ISO file." -ForegroundColor Yellow
  235. exit 1
  236. }
  237.  
  238. Write-Host "URL validation successful. Proceeding with download..." -ForegroundColor Green
  239. $isLocalFile = $false
  240. }
  241.  
  242. # Download ISO if needed
  243. if (-not $isLocalFile) {
  244. Write-Host "Downloading Windows 11 ISO..." -ForegroundColor Cyan
  245. Write-Host "This may take some time depending on your internet connection speed." -ForegroundColor Cyan
  246.  
  247. try {
  248. $webClient = New-Object System.Net.WebClient
  249. $webClient.Headers.Add("User-Agent", "Mozilla/5.0 Windows PowerShell Script")
  250.  
  251. # Disable progress bar to improve download performance
  252. $ProgressPreference = 'SilentlyContinue'
  253.  
  254. Write-Host "Download started at $(Get-Date)" -ForegroundColor Cyan
  255. $webClient.DownloadFile($isoUrl, $isoPath)
  256. Write-Host "Download completed at $(Get-Date)" -ForegroundColor Green
  257.  
  258. # Restore progress preference
  259. $ProgressPreference = 'Continue'
  260.  
  261. # Verify the download
  262. if (Test-Path $isoPath) {
  263. $fileInfo = Get-Item $isoPath
  264. $fileSizeMB = [math]::Round($fileInfo.Length / 1MB, 2)
  265.  
  266. # Check if file size is reasonable for a Windows ISO
  267. if ($fileSizeMB -lt 3000) {
  268. Write-Host "Warning: The downloaded ISO is only $fileSizeMB MB, which is unusually small for a Windows 11 ISO." -ForegroundColor Yellow
  269. Write-Host "This might indicate a partial download or incorrect ISO source." -ForegroundColor Yellow
  270. if (-not $BYPASS_CONFIRMATION) {
  271. $continue = Read-Host "Do you want to continue anyway? (y/n)"
  272. if ($continue -ne 'y' -and $continue -ne 'Y') {
  273. Write-Host "Operation cancelled by user."
  274. exit 0
  275. }
  276. } else {
  277. Write-Host "Confirmation bypassed. Continuing despite small downloaded ISO size..." -ForegroundColor Yellow
  278. }
  279. } else {
  280. Write-Host "ISO downloaded successfully ($fileSizeMB MB)." -ForegroundColor Green
  281. }
  282. } else {
  283. throw "ISO download failed: File not found after download"
  284. }
  285. } catch {
  286. Write-Error "Failed to download the ISO: $_"
  287. exit 1
  288. } finally {
  289. # Ensure WebClient is disposed
  290. if ($webClient) {
  291. $webClient.Dispose()
  292. }
  293. }
  294. } else {
  295. Write-Host "ISO file ready: $isoPath" -ForegroundColor Green
  296. }
  297.  
  298. # Create a working directory for extracted ISO content
  299. $extractDir = $WORKING_DIR
  300. if (Test-Path $extractDir) {
  301. # Clean any existing directory to avoid conflicts
  302. Write-Host "Cleaning existing working directory..."
  303. Remove-Item -Path "$extractDir\*" -Recurse -Force -ErrorAction SilentlyContinue
  304. } else {
  305. # Create new directory
  306. New-Item -Path $extractDir -ItemType Directory -Force | Out-Null
  307. }
  308.  
  309. # Check for 7-Zip installation
  310. $7zipPath = "C:\Program Files\7-Zip\7z.exe"
  311. if (-not (Test-Path $7zipPath)) {
  312. # Try common alternative path for x86 on x64 systems
  313. $7zipPath = "C:\Program Files (x86)\7-Zip\7z.exe"
  314. if (-not (Test-Path $7zipPath)) {
  315. Write-Host "7-Zip not found. Attempting to download and install it..."
  316.  
  317. # Download and install 7-Zip using dynamic method to get latest version
  318. try {
  319. # Settings
  320. $downloadPage = "https://www.7-zip.org/download.html"
  321. $downloadPath = "C:\Windows\Temp\7z.msi"
  322.  
  323. # Download page content
  324. $webClient = New-Object System.Net.WebClient
  325. $htmlContent = $webClient.DownloadString($downloadPage)
  326.  
  327. # Extract latest x64 MSI link from the current version section
  328. $latestSection = $htmlContent -split '<P><B>Download 7-Zip' | Select-Object -Index 1
  329.  
  330. # Handle both 32-bit and 64-bit architectures
  331. if ([Environment]::Is64BitOperatingSystem) {
  332. $archPattern = '-x64\.msi'
  333. } else {
  334. $archPattern = '\.msi"'
  335. }
  336.  
  337. $msiRelativePath = ($latestSection | Select-String -Pattern "href=`"(a/7z\d+.*?$($archPattern))" -AllMatches).Matches[0].Groups[1].Value
  338.  
  339. # Construct full download URL
  340. $downloadUrl = "https://www.7-zip.org/$msiRelativePath"
  341.  
  342. Write-Host "Downloading 7-Zip from $downloadUrl"
  343.  
  344. # Download and install
  345. $webClient.DownloadFile($downloadUrl, $downloadPath)
  346. Start-Process msiexec.exe -ArgumentList "/i `"$downloadPath`" /quiet /norestart" -Wait
  347.  
  348. # Verify installation
  349. if (-not (Test-Path "C:\Program Files\7-Zip\7z.exe")) {
  350. throw "Failed to install 7-Zip"
  351. }
  352. $7zipPath = "C:\Program Files\7-Zip\7z.exe"
  353. } catch {
  354. Write-Error "Failed to install 7-Zip: $_"
  355. Write-Error "Please install 7-Zip manually and try again."
  356. exit 1
  357. }
  358. }
  359. }
  360.  
  361. # Extract ISO using 7-Zip
  362. Write-Host "Extracting ISO using 7-Zip (this may take 5-10 minutes)..." -ForegroundColor Cyan
  363. Write-Host "Please be patient while the ISO contents are extracted..." -ForegroundColor Cyan
  364. try {
  365. # Use Start-Process with redirected error streams to capture output without displaying it
  366. $processInfo = New-Object System.Diagnostics.ProcessStartInfo
  367. $processInfo.FileName = $7zipPath
  368. $processInfo.Arguments = "x -y -o`"$extractDir`" `"$isoPath`""
  369. $processInfo.RedirectStandardError = $true
  370. $processInfo.RedirectStandardOutput = $true
  371. $processInfo.UseShellExecute = $false
  372. $processInfo.CreateNoWindow = $true
  373.  
  374. $process = New-Object System.Diagnostics.Process
  375. $process.StartInfo = $processInfo
  376. $process.Start() | Out-Null
  377.  
  378. # Record start time
  379. $startTime = Get-Date
  380.  
  381. # Wait for process to complete (no spinner)
  382. $process.WaitForExit()
  383.  
  384. # Show completion message with total time
  385. $extractionTime = [TimeSpan]::FromSeconds((Get-Date).Subtract($startTime).TotalSeconds)
  386. Write-Host "Extraction complete [" $extractionTime.ToString("hh\:mm\:ss") "]" -ForegroundColor Green
  387.  
  388. # Get the output without displaying it
  389. $standardOutput = $process.StandardOutput.ReadToEnd()
  390. $standardError = $process.StandardError.ReadToEnd()
  391.  
  392. # Check the exit code
  393. if ($process.ExitCode -ne 0) {
  394. # Format a user-friendly error message without dumping everything
  395. Write-Host "ERROR: 7-Zip extraction failed with exit code $($process.ExitCode)" -ForegroundColor Red
  396. Write-Host "The ISO file may be corrupted or incompatible." -ForegroundColor Yellow
  397.  
  398. # Show minimal error information
  399. if (-not [string]::IsNullOrEmpty($standardError)) {
  400. $errorLines = $standardError -split "`n"
  401. $relevantError = ($errorLines | Where-Object { $_ -match "ERROR:" } | Select-Object -First 1)
  402. if ($relevantError) {
  403. Write-Host "Error details: $relevantError" -ForegroundColor Yellow
  404. }
  405. }
  406.  
  407. exit 1
  408. }
  409.  
  410. # Verify extraction succeeded
  411. $setupPath = "$extractDir\setup.exe"
  412. if (-not (Test-Path $setupPath)) {
  413. Write-Host "ERROR: Extraction completed but setup.exe was not found." -ForegroundColor Red
  414. Write-Host "This suggests the ISO does not contain a valid Windows installation." -ForegroundColor Yellow
  415. Write-Host "Please verify you are using a proper Windows 11 installation ISO." -ForegroundColor Yellow
  416. exit 1
  417. }
  418.  
  419. Write-Host "ISO extracted successfully to $extractDir" -ForegroundColor Green
  420.  
  421. # Create zero-byte appraiserres.dll to bypass TPM check
  422. Write-Host "Creating TPM check bypass..."
  423. $appraiserdllPath = "$extractDir\sources\appraiserres.dll"
  424. if (Test-Path $appraiserdllPath) {
  425. # Make a backup just in case
  426. Copy-Item -Path $appraiserdllPath -Destination "$appraiserdllPath.bak" -Force
  427. # Replace with zero-byte file
  428. Set-Content -Path $appraiserdllPath -Value "" -Force
  429. } else {
  430. # Create new zero-byte file if it doesn't exist
  431. New-Item -Path $appraiserdllPath -ItemType File -Force | Out-Null
  432. }
  433.  
  434. # Create EI.cfg to avoid product key prompts
  435. $eiCfgPath = "$extractDir\sources\EI.cfg"
  436. Set-Content -Path $eiCfgPath -Value "[Channel]`n_Default" -Force
  437.  
  438. # Create SetupConfig.ini
  439. $setupConfigPath = "$extractDir\sources\SetupConfig.ini"
  440. $setupConfig = @"
  441. [BeginSetupMode]
  442. SkipPrediagler=1
  443. DeviceEnumeration=1
  444. DiscoverSystemPartition=1
  445.  
  446. [SetupConfig]
  447. ScratchDir=$env:SystemDrive\`$WINDOWS.~BT
  448. ScratchSpace=12000
  449. PreinstallKitSpace=8000
  450. "@
  451. Set-Content -Path $setupConfigPath -Value $setupConfig -Force
  452.  
  453. # Run setup.exe with appropriate arguments and stronger compatibility bypass options
  454. Write-Host "Starting Windows 11 upgrade from extracted ISO with maximum compatibility overrides..."
  455.  
  456. # Create custom answer file to force upgrade
  457. $answerFilePath = "$extractDir\unattend.xml"
  458. $answerFileContent = @"
  459. <unattend xmlns="urn:schemas-microsoft-com:unattend">
  460. <settings pass="windowsPE">
  461. <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
  462. <ComplianceCheck>
  463. <DisplayReport>Never</DisplayReport>
  464. </ComplianceCheck>
  465. <Diagnostics>
  466. <OptIn>false</OptIn>
  467. </Diagnostics>
  468. <DynamicUpdate>
  469. <Enable>true</Enable>
  470. <WillShowUI>OnError</WillShowUI>
  471. </DynamicUpdate>
  472. <ImageInstall>
  473. <OSImage>
  474. <InstallFrom>
  475. <MetaData>
  476. <Key>/IMAGE/INDEX</Key>
  477. <Value>1</Value>
  478. </MetaData>
  479. </InstallFrom>
  480. <InstallTo>
  481. <DiskID>0</DiskID>
  482. <PartitionID>1</PartitionID>
  483. </InstallTo>
  484. <WillShowUI>OnError</WillShowUI>
  485. <InstallToAvailablePartition>true</InstallToAvailablePartition>
  486. </OSImage>
  487. </ImageInstall>
  488. <UserData>
  489. <AcceptEula>true</AcceptEula>
  490. </UserData>
  491. <RunSynchronous>
  492. <RunSynchronousCommand wcm:action="add">
  493. <Order>1</Order>
  494. <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /d 1 /t reg_dword /f</Path>
  495. </RunSynchronousCommand>
  496. <RunSynchronousCommand wcm:action="add">
  497. <Order>2</Order>
  498. <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /d 1 /t reg_dword /f</Path>
  499. </RunSynchronousCommand>
  500. <RunSynchronousCommand wcm:action="add">
  501. <Order>3</Order>
  502. <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassRAMCheck /d 1 /t reg_dword /f</Path>
  503. </RunSynchronousCommand>
  504. <RunSynchronousCommand wcm:action="add">
  505. <Order>4</Order>
  506. <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassCPUCheck /d 1 /t reg_dword /f</Path>
  507. </RunSynchronousCommand>
  508. <RunSynchronousCommand wcm:action="add">
  509. <Order>5</Order>
  510. <Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassStorageCheck /d 1 /t reg_dword /f</Path>
  511. </RunSynchronousCommand>
  512. <RunSynchronousCommand wcm:action="add">
  513. <Order>6</Order>
  514. <Path>reg add HKLM\SYSTEM\Setup\MoSetup /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword /f</Path>
  515. </RunSynchronousCommand>
  516. </RunSynchronous>
  517. </component>
  518. </settings>
  519. </unattend>
  520. "@
  521. Set-Content -Path $answerFilePath -Value $answerFileContent -Force
  522. Write-Host "Created custom unattend.xml file for compatibility bypass"
  523.  
  524. # Try the alternate 'Server' product trick - update setup files
  525. Write-Host "Applying 'Server' product trick to bypass hardware checks..."
  526. try {
  527. $setupConfigDatPath = "$extractDir\sources\setupconfig.dat"
  528. if (Test-Path $setupConfigDatPath) {
  529. $content = Get-Content -Path $setupConfigDatPath -Encoding Byte
  530. $clientPattern = [System.Text.Encoding]::Unicode.GetBytes("Client")
  531. $serverPattern = [System.Text.Encoding]::Unicode.GetBytes("Server")
  532.  
  533. $found = $false
  534. for ($i = 0; $i -lt $content.Length - $clientPattern.Length; $i++) {
  535. $matched = $true
  536. for ($j = 0; $j -lt $clientPattern.Length; $j++) {
  537. if ($content[$i + $j] -ne $clientPattern[$j]) {
  538. $matched = $false
  539. break
  540. }
  541. }
  542.  
  543. if ($matched) {
  544. $found = $true
  545. for ($j = 0; $j -lt $serverPattern.Length; $j++) {
  546. $content[$i + $j] = $serverPattern[$j]
  547. }
  548. }
  549. }
  550.  
  551. if ($found) {
  552. [System.IO.File]::WriteAllBytes($setupConfigDatPath, $content)
  553. Write-Host "Successfully modified setupconfig.dat to use Server edition bypass"
  554. }
  555. }
  556. } catch {
  557. Write-Host "Warning: Could not modify setupconfig.dat: $_"
  558. }
  559. # Setup command line arguments
  560. $arguments = @(
  561. "/auto", "upgrade",
  562. "/quiet",
  563. "/compat", "ignorewarning",
  564. "/migratedrivers", "all",
  565. "/showoobe", "none",
  566. "/telemetry", "disable",
  567. "/dynamicupdate", "enable",
  568. "/eula", "accept",
  569. "/unattend:$answerFilePath",
  570. "/product", "server", # Add server product parameter to bypass hardware checks
  571. "/pkey", "VK7JG-NPHTM-C97JM-9MPGT-3V66T" # Generic Windows 11 Pro key
  572. )
  573.  
  574. # Add /noreboot switch if automatic reboots are disabled
  575. if (-not $ALLOW_AUTOMATIC_REBOOT) {
  576. $arguments += "/noreboot"
  577. Write-Host "Automatic reboots are disabled. The system will need to be manually rebooted to complete the upgrade."
  578. } else {
  579. Write-Host "Automatic reboots are enabled. The system will reboot automatically when needed."
  580. }
  581.  
  582. # Create a log file to track progress
  583. $logFile = $LOG_FILE
  584. Set-Content -Path $logFile -Value "Windows 11 Upgrade started at $(Get-Date)`r`n" -Force
  585.  
  586. # Function to log progress
  587. function Write-ProgressLog {
  588. param(
  589. [string]$Message
  590. )
  591. $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
  592. $logMessage = "[$timestamp] $Message"
  593. Write-Host $logMessage
  594. Add-Content -Path $logFile -Value $logMessage
  595. }
  596.  
  597. # Function to check if Windows Setup is running
  598. function Is-SetupRunning {
  599. $setupProcesses = @(
  600. "SetupHost", # This is the critical process for actual Windows upgrade execution
  601. "setupprep",
  602. "setup",
  603. "Windows10UpgraderApp"
  604. )
  605.  
  606. foreach ($proc in $setupProcesses) {
  607. $running = Get-Process -Name $proc -ErrorAction SilentlyContinue
  608. if ($running) {
  609. if ($proc -eq "SetupHost") {
  610. Write-ProgressLog "CRITICAL SUCCESS: SetupHost.exe is running! This confirms the upgrade is properly underway."
  611. return @{Success = $true; Critical = $true}
  612. }
  613. return @{Success = $true; Critical = $false}
  614. }
  615. }
  616. return @{Success = $false; Critical = $false}
  617. }
  618.  
  619. # Function to wait for SetupHost.exe to appear (the definitive sign that upgrade is working)
  620. function Wait-ForSetupHost {
  621. param (
  622. [int]$TimeoutSeconds = 300, # Wait up to 5 minutes by default
  623. [int]$CheckIntervalSeconds = 5
  624. )
  625.  
  626. Write-ProgressLog "Waiting for SetupHost.exe to start (the critical process for Windows upgrades)..."
  627.  
  628. $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
  629. $timeoutMs = $TimeoutSeconds * 1000
  630.  
  631. while ($stopwatch.ElapsedMilliseconds -lt $timeoutMs) {
  632. $setupHost = Get-Process -Name "SetupHost" -ErrorAction SilentlyContinue
  633. if ($setupHost) {
  634. $stopwatch.Stop()
  635. Write-ProgressLog "SUCCESS: SetupHost.exe started after $([math]::Round($stopwatch.ElapsedMilliseconds / 1000)) seconds."
  636. Write-ProgressLog "SetupHost.exe PID: $($setupHost.Id), Started at: $(Get-Date)"
  637. return $true
  638. }
  639.  
  640. # Check for setupprep - it should start first and launch SetupHost
  641. $setupPrep = Get-Process -Name "setupprep" -ErrorAction SilentlyContinue
  642. if ($setupPrep) {
  643. Write-ProgressLog "setupprep.exe is running (PID: $($setupPrep.Id)). Waiting for it to launch SetupHost.exe..."
  644. }
  645.  
  646. # Sleep before checking again
  647. Start-Sleep -Seconds $CheckIntervalSeconds
  648. }
  649.  
  650. $stopwatch.Stop()
  651. Write-ProgressLog "WARNING: SetupHost.exe did not start within $TimeoutSeconds seconds."
  652. return $false
  653. }
  654.  
  655. Write-ProgressLog "Starting Windows 11 upgrade from extracted ISO..."
  656. Write-ProgressLog "To monitor progress, check the log file at: $logFile"
  657. Write-ProgressLog "You can also look for these processes: SetupHost.exe, setupprep.exe, setup.exe"
  658.  
  659. # Start setup without waiting
  660. $arguments += "/PostOOBE", "$extractDir\PostInstall.cmd"
  661.  
  662. # Create a post-install script to log completion
  663. $postInstallScript = @"
  664. @echo off
  665. echo Windows 11 Upgrade completed at %DATE% %TIME% > C:\Win11_Upgrade_Completed.log
  666. "@
  667. Set-Content -Path "$extractDir\PostInstall.cmd" -Value $postInstallScript -Force
  668.  
  669. # Start the setup process
  670. Write-ProgressLog "Launching setup.exe with arguments: $($arguments -join ' ')"
  671. $process = Start-Process -FilePath $setupPath -ArgumentList $arguments -PassThru -NoNewWindow
  672.  
  673. # Wait briefly to see if initial processes start
  674. Start-Sleep -Seconds 5
  675.  
  676. # Check if setup is running and log process ID
  677. $setupStatus = Is-SetupRunning
  678. if ($setupStatus.Success) {
  679. $setupProcesses = Get-Process | Where-Object { $_.Name -match "setup|SetupHost" }
  680. foreach ($proc in $setupProcesses) {
  681. Write-ProgressLog "Setup process running: $($proc.Name) (PID: $($proc.Id))"
  682. }
  683.  
  684. if ($setupStatus.Critical) {
  685. Write-ProgressLog "VERIFIED: SetupHost.exe is running! The upgrade is confirmed to be properly underway."
  686. } else {
  687. # SetupHost is not yet running - wait for it as it's the critical indicator
  688. Write-ProgressLog "Initial setup processes started, but waiting for SetupHost.exe (the critical component)..."
  689.  
  690. # Wait for SetupHost to appear - this is the definitive test
  691. $setupHostStarted = Wait-ForSetupHost -TimeoutSeconds 600 # Wait up to 10 minutes
  692.  
  693. if ($setupHostStarted) {
  694. Write-ProgressLog "UPGRADE CONFIRMED: SetupHost.exe is running. The Windows 11 upgrade is now definitely underway."
  695. Write-ProgressLog "This is the critical process that indicates the actual upgrade is proceeding correctly."
  696. } else {
  697. Write-ProgressLog "WARNING: SetupHost.exe did not start within the expected timeframe."
  698. Write-ProgressLog "The upgrade may still proceed, but you should monitor it carefully."
  699. Write-ProgressLog "If the upgrade does not complete, you may need to run the script again."
  700. }
  701. }
  702.  
  703. Write-ProgressLog "Setup initiated. The upgrade is now running in the background."
  704. Write-ProgressLog "To check if it's running, use Task Manager to look for SetupHost.exe."
  705. } else {
  706. Write-ProgressLog "Warning: Setup may not have started correctly."
  707. Write-ProgressLog "Checking exit code: $($process.ExitCode)"
  708.  
  709. # Try alternative approach - direct setupprep.exe execution with Server trick
  710. Write-ProgressLog "Trying alternative approach with setupprep.exe and Server trick..."
  711. $setupPrepPath = "$extractDir\sources\setupprep.exe"
  712. if (Test-Path $setupPrepPath) {
  713. # Prepare $WINDOWS.~BT directory
  714. $btDir = "$env:SystemDrive\`$WINDOWS.~BT\Sources"
  715. if (-not (Test-Path $btDir)) {
  716. New-Item -Path $btDir -ItemType Directory -Force | Out-Null
  717. }
  718.  
  719. # Copy critical files to ensure Windows.~BT has what it needs
  720. Write-ProgressLog "Copying setup files to Windows.~BT directory..."
  721. Copy-Item -Path "$extractDir\sources\*" -Destination $btDir -Force -Recurse
  722.  
  723. # Create zero-byte appraiserres.dll in Windows.~BT
  724. Set-Content -Path "$btDir\appraiserres.dll" -Value "" -Force
  725.  
  726. # Add additional bypass files
  727. Set-Content -Path "$btDir\Skip.cmd" -Value @"
  728. @echo off
  729. reg add HKLM\SYSTEM\Setup\MoSetup /f /v AllowUpgradesWithUnsupportedTPMorCPU /d 1 /t reg_dword
  730. reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassTPMCheck /d 1 /t reg_dword
  731. reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassSecureBootCheck /d 1 /t reg_dword
  732. reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassRAMCheck /d 1 /t reg_dword
  733. reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassStorageCheck /d 1 /t reg_dword
  734. reg add HKLM\SYSTEM\Setup\LabConfig /f /v BypassCPUCheck /d 1 /t reg_dword
  735. reg add HKLM\SYSTEM\Setup /f /v BypassComponentCheck /d 1 /t reg_dword
  736. "@ -Force
  737.  
  738. # Modify the EditionID to ensure compatibility
  739. $regScript = @"
  740. Windows Registry Editor Version 5.00
  741.  
  742. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion]
  743. "EditionID_undo"="Professional"
  744. "EditionID"="Professional"
  745. "ProductName"="Windows 11 Pro"
  746. "@
  747. Set-Content -Path "$btDir\edition.reg" -Value $regScript -Force
  748.  
  749. # Create batch file to run registry changes and launch setup
  750. $setupBatchPath = "$btDir\RunSetup.cmd"
  751.  
  752. $setupCommand = "setupprep.exe /product server /auto upgrade /quiet /compat ignorewarning /migratedrivers all /dynamicupdate enable /eula accept"
  753.  
  754. # Add noreboot switch if automatic reboots are disabled
  755. if (-not $ALLOW_AUTOMATIC_REBOOT) {
  756. $setupCommand += " /noreboot"
  757. }
  758.  
  759. $setupBatch = @"
  760. @echo off
  761. cd /d "%~dp0"
  762. call Skip.cmd
  763. regedit /s edition.reg
  764. $setupCommand
  765. "@
  766. Set-Content -Path $setupBatchPath -Value $setupBatch -Force
  767.  
  768. # Run the batch file to execute setup with all bypasses
  769. Write-ProgressLog "Launching setup with all compatibility bypasses..."
  770. Start-Process -FilePath "cmd.exe" -ArgumentList "/c $setupBatchPath" -PassThru -NoNewWindow
  771.  
  772. # Wait briefly to check if it started
  773. Start-Sleep -Seconds 5
  774.  
  775. # Check again if setup is running
  776. $setupStatus = Is-SetupRunning
  777. if ($setupStatus.Success) {
  778. $setupProcesses = Get-Process | Where-Object { $_.Name -match "setup|SetupHost" }
  779. foreach ($proc in $setupProcesses) {
  780. Write-ProgressLog "Setup process running: $($proc.Name) (PID: $($proc.Id))"
  781. }
  782.  
  783. if ($setupStatus.Critical) {
  784. Write-ProgressLog "VERIFIED: SetupHost.exe is running via fallback method! The upgrade is confirmed to be properly underway."
  785. } else {
  786. # SetupHost is not yet running - wait for it as it's the critical indicator
  787. Write-ProgressLog "Initial setup processes started via fallback method, waiting for SetupHost.exe..."
  788.  
  789. # Wait for SetupHost to appear - this is the definitive test
  790. $setupHostStarted = Wait-ForSetupHost -TimeoutSeconds 600 # Wait up to 10 minutes
  791.  
  792. if ($setupHostStarted) {
  793. Write-ProgressLog "UPGRADE CONFIRMED: SetupHost.exe is running. The Windows 11 upgrade is now definitely underway."
  794. } else {
  795. Write-ProgressLog "WARNING: SetupHost.exe did not start within the expected timeframe."
  796. Write-ProgressLog "The upgrade may still proceed, but monitoring is recommended."
  797. }
  798. }
  799.  
  800. Write-ProgressLog "Setup initiated via fallback method. The upgrade is now running in the background."
  801. } else {
  802. Write-ProgressLog "WARNING: Both setup methods failed to start the upgrade process."
  803. Write-ProgressLog "Please check the logs and consider running the script again."
  804. }
  805. }
  806.  
  807. # Create a simple monitor script that only logs progress
  808. $monitorScript = @"
  809. @echo off
  810. echo Windows 11 upgrade monitor started at %DATE% %TIME% > "%MONITOR_LOG%"
  811.  
  812. :check
  813. echo ------------------------------------------------ >> "%MONITOR_LOG%"
  814. echo Checking processes at %DATE% %TIME% >> "%MONITOR_LOG%"
  815. tasklist /fi "imagename eq setuphost.exe" >> "%MONITOR_LOG%"
  816. tasklist /fi "imagename eq setupprep.exe" >> "%MONITOR_LOG%"
  817. tasklist /fi "imagename eq setup.exe" >> "%MONITOR_LOG%"
  818.  
  819. REM Check if RebootRequired registry exists (for logging only)
  820. reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" > nul 2>&1
  821. if %ERRORLEVEL% EQU 0 (
  822. echo Reboot Required registry key found! Windows should reboot automatically. >> "%MONITOR_LOG%"
  823. )
  824.  
  825. REM Check if installation phase registry indicates readiness (for logging only)
  826. reg query "HKLM\SYSTEM\Setup" /v SystemSetupInProgress > nul 2>&1
  827. if %ERRORLEVEL% EQU 0 (
  828. for /f "tokens=3" %%a in ('reg query "HKLM\SYSTEM\Setup" /v SystemSetupInProgress ^| find "SystemSetupInProgress"') do set SETUP_PROGRESS=%%a
  829. echo SystemSetupInProgress value: !SETUP_PROGRESS! >> "%MONITOR_LOG%"
  830. )
  831.  
  832. REM Log recent activity in setup logs
  833. echo Recent setup logs: >> "%MONITOR_LOG%"
  834. dir /a-d /od C:\$WINDOWS.~BT\Sources\Panther\*.log >> "%MONITOR_LOG%" 2>&1
  835.  
  836. REM Log memory info to monitor system health
  837. echo Memory status: >> "%MONITOR_LOG%"
  838. systeminfo | find "Physical Memory" >> "%MONITOR_LOG%"
  839. echo. >> "%MONITOR_LOG%"
  840.  
  841. timeout /t 300 > nul
  842. goto check
  843. "@
  844. Set-Content -Path "$extractDir\MonitorSetup.cmd" -Value $monitorScript -Force
  845.  
  846. # Start the monitor script in a hidden window
  847. Start-Process -FilePath "cmd.exe" -ArgumentList "/c $extractDir\MonitorSetup.cmd" -WindowStyle Hidden
  848. }
  849.  
  850. # Clean up - delete the downloaded ISO but keep extracted files for debugging
  851. Remove-Item -Path $isoPath -Force -ErrorAction SilentlyContinue
  852.  
  853. } catch {
  854. # Extract only the essential error message without the full stack trace
  855. $errorMessage = $_.Exception.Message
  856. if ($errorMessage.Length -gt 150) {
  857. $errorMessage = $errorMessage.Substring(0, 150) + "..."
  858. }
  859.  
  860. # Create a clean, user-friendly error message
  861. $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."
  862.  
  863. # Try to clean up
  864. try {
  865. Remove-Item -Path $isoPath -Force -ErrorAction SilentlyContinue
  866. } catch {
  867. # Ignore cleanup errors
  868. }
  869.  
  870. # Show clean error message
  871. Write-Host "ERROR: Windows 11 upgrade process failed." -ForegroundColor Red
  872. Write-Host "The Windows 11 upgrade process encountered an issue and could not continue." -ForegroundColor Yellow
  873. Write-Host "Try again or check the log file at $logFile for more details." -ForegroundColor Yellow
  874. exit 1
  875. }
  876.  
  877. # Final progress information and verification
  878. if ($ALLOW_AUTOMATIC_REBOOT) {
  879. Write-ProgressLog "Windows 11 upgrade process initiated. The system will reboot automatically when the upgrade is complete."
  880. } else {
  881. Write-ProgressLog "Windows 11 upgrade process initiated. Manual reboot will be required when the upgrade preparation is complete."
  882. }
  883. Write-ProgressLog ""
  884. Write-ProgressLog "To verify the upgrade is running, check for these files:"
  885. Write-ProgressLog "- $logFile - Contains detailed progress information"
  886. Write-ProgressLog "- $MONITOR_LOG - Contains periodic process checks every 5 minutes"
  887. Write-ProgressLog "- C:\Win11_Upgrade_Completed.log - Will be created when upgrade completes"
  888. Write-ProgressLog ""
  889. Write-ProgressLog "You should also see one or more of these processes in Task Manager:"
  890. Write-ProgressLog "- SetupHost.exe - Main upgrade process"
  891. Write-ProgressLog "- setupprep.exe - Preparation process"
  892. Write-ProgressLog "- setup.exe - Initial setup launcher"
  893. Write-ProgressLog ""
  894. Write-ProgressLog "Process monitoring is active but no automatic intervention will occur."
  895. Write-ProgressLog "Windows Setup will handle the reboot process organically when ready."
  896.  
  897. # One final check to make absolutely sure SetupHost is running
  898. Write-ProgressLog "Performing final verification to ensure SetupHost.exe is running..."
  899. Start-Sleep -Seconds 15
  900.  
  901. $setupHost = Get-Process -Name "SetupHost" -ErrorAction SilentlyContinue
  902. if ($setupHost) {
  903. Write-ProgressLog "FINAL VERIFICATION PASSED: SetupHost.exe is running (PID: $($setupHost.Id))."
  904. Write-ProgressLog "The Windows 11 upgrade is definitely underway and proceeding properly."
  905. Write-ProgressLog "This is the CRITICAL process that confirms the upgrade will complete successfully."
  906.  
  907. # Log all running setup processes for completeness
  908. $setupProcesses = Get-Process | Where-Object { $_.Name -match "setup|SetupHost" }
  909. Write-ProgressLog "All running setup processes:"
  910. foreach ($proc in $setupProcesses) {
  911. Write-ProgressLog "- $($proc.Name) (PID: $($proc.Id))"
  912. }
  913.  
  914. Write-ProgressLog "UPGRADE STATUS: SUCCESS - The script has successfully initiated the Windows 11 upgrade."
  915. } else {
  916. # SetupHost is still not running - check for any setup processes
  917. $setupStatus = Is-SetupRunning
  918. if ($setupStatus.Success) {
  919. Write-ProgressLog "WARNING: Setup processes are running, but SetupHost.exe has not started yet."
  920. Write-ProgressLog "The upgrade may still proceed, but it's recommended to monitor the process."
  921. Write-ProgressLog "If needed, check the C:\$WINDOWS.~BT\Sources\Panther directory for logs."
  922.  
  923. # One last attempt to wait for SetupHost
  924. Write-ProgressLog "Making final attempt to wait for SetupHost.exe to start..."
  925. $finalAttempt = Wait-ForSetupHost -TimeoutSeconds 300 # Wait 5 more minutes
  926.  
  927. if ($finalAttempt) {
  928. Write-ProgressLog "SUCCESS: SetupHost.exe has finally started. The upgrade is now properly underway."
  929. } else {
  930. Write-ProgressLog "CAUTION: SetupHost.exe still not detected. The upgrade process may be abnormal."
  931. Write-ProgressLog "Please monitor the system to ensure the upgrade completes successfully."
  932. }
  933. } else {
  934. Write-ProgressLog "CRITICAL WARNING: No setup processes are running. The upgrade has likely failed to start."
  935. Write-ProgressLog "Check C:\$WINDOWS.~BT\Sources\Panther directory for setupact.log and setuperr.log files"
  936. Write-ProgressLog "You may need to run the script again or try a different approach."
  937. }
  938. }
Add Comment
Please, Sign In to add comment