Testing Windows 10 in-place upgrade task sequence

I’ve been trying to make smaller/quicker task sequences for doing Windows 10 in-place upgrades. I wanted to be able to get almost everything done hidden in the background (Setting variable TSDisableProgressUI to True) before the first restart would even prompt.

I noticed by using the step ‘Upgrade Operating System’ it will automatically reboot when the setup requests. I tried increasing the variable SMSTSRebootTimeout so the first prompt would give users enough time if someone was logged on. The problem with this is that there will be more than one prompt which isn’t necessary after the first as the upgrade isn’t done yet.

I know if you manually run the setup.exe with /noreboot it will do as much as it can and then just wait until a reboot is performed so I figured I would test that in a task sequence with a ‘Run Command Line’ instead.

I pre-download the Operating System upgrade package, saving the path as a variable (I download it separate from any other packages just so the variable is definitely OSUpgrade01). Just before running the setup, I run a powershell create to create new ‘SetupComplete’ files.

# Create SetupComplete for SCCM Upgrade
$SCCMClientPath = "$env:WinDir\CCM"
If (Test-Path "$env:SystemDrive\_SMSTaskSequence\Packages") {
	$SMSTSMDataPath = "$env:SystemDrive\_SMSTaskSequence"
} Else {
	$Drives = (Get-PSDrive | Where-Object {$_.Provider -like "*FileSystem*"} | Where-Object {$null -ne $_.Free} | Where-Object {$_.DisplayRoot -notlike "\\*"}).Root
	ForEach ($Drive in $Drives) {
		If (Test-Path "$($Drive)_SMSTaskSequence\Packages") {
			$SMSTSMDataPath = "$($Drive)_SMSTaskSequence"
		}
	}
}
If ((Test-Path "$SCCMClientPath") -And ($null -ne $SMSTSMDataPath)) {
	$Setup = "$SCCMClientPath\SetupCompleteUpgrade.cmd"
	New-Item -Path "$Setup" -Value '@ECHO OFF' -Force | Out-Null
	Add-Content -Path "$Setup" -Value '' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Entering setupcomplete.cmd >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Setting env var _SMSTSSetupRollback=FALSE >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'set _SMSTSSetupRollback=FALSE' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Resetting services back to original settings >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'sc config ccmexec start= auto' -Force
	Add-Content -Path "$Setup" -Value 'sc config smstsmgr start= demand' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Starting service CcmExec >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'sc start ccmexec' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Setting registry to resume task sequence after reboot >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'reg add HKLM\SYSTEM\Setup /v SetupType /t REG_DWORD /d 2 /f' -Force
	Add-Content -Path "$Setup" -Value "reg add HKLM\SYSTEM\Setup /v CmdLine /t REG_SZ /d ""$($Setup)"" /f" -Force
	Add-Content -Path "$Setup" -Value '' -Force
	Add-Content -Path "$Setup" -Value "echo %DATE%-%TIME% Running $($SCCMClientPath)\\TSMBootstrap.exe to resume task sequence >> %WINDIR%\setupcomplete.log" -Force
	Add-Content -Path "$Setup" -Value "$($SCCMClientPath)\\TSMBootstrap.exe /env:Gina /configpath:$($SMSTSMDataPath) /bootcount:2 /reloadenv" -Force
	Add-Content -Path "$Setup" -Value '' -Force
	Add-Content -Path "$Setup" -Value 'IF %ERRORLEVEL% EQU -2147021886 (' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% ERRORLEVEL = %ERRORLEVEL%  >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% TSMBootstrap requested reboot >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Rebooting now >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'reg add HKLM\SYSTEM\Setup /v SetupShutdownRequired /t REG_DWORD /d 1 /f' -Force
	Add-Content -Path "$Setup" -Value ') else (' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% ERRORLEVEL = %ERRORLEVEL%  >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% TSMBootstrap did not request reboot, resetting registry >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Setup" -Value 'reg add HKLM\SOFTWARE\Microsoft\CCM\CcmExec /v ProvisioningMode /t REG_SZ /d "false" /f' -Force
	Add-Content -Path "$Setup" -Value 'reg add HKLM\SYSTEM\Setup /v SetupType /t REG_DWORD /d 0 /f' -Force
	Add-Content -Path "$Setup" -Value 'reg add HKLM\SYSTEM\Setup /v CmdLine /t REG_SZ /d "" /f' -Force
	Add-Content -Path "$Setup" -Value ')' -Force
	Add-Content -Path "$Setup" -Value 'echo %DATE%-%TIME% Exiting setupcomplete.cmd >> %WINDIR%\setupcomplete.log' -Force
	
	$Rollback = "$SCCMClientPath\SetupRollbackUpgrade.cmd"
	New-Item -Path "$Rollback" -Value '@ECHO OFF' -Force | Out-Null
	Add-Content -Path "$Rollback" -Value '' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Entering setuprollback.cmd >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Setting env var _SMSTSSetupRollback=TRUE >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'set _SMSTSSetupRollback=TRUE' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Resetting services back to original settings >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Rollback" -Value 'sc config ccmexec start= auto' -Force
	Add-Content -Path "$Rollback" -Value 'sc config smstsmgr start= demand' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Starting service CcmExec >> %WINDIR%\setupcomplete.log' -Force
	Add-Content -Path "$Rollback" -Value 'sc start ccmexec' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Setting registry to resume task sequence after reboot >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'reg add HKLM\SYSTEM\Setup /v SetupType /t REG_DWORD /d 2 /f' -Force
	Add-Content -Path "$Rollback" -Value "reg add HKLM\SYSTEM\Setup /v CmdLine /t REG_SZ /d ""$($Rollback)"" /f" -Force
	Add-Content -Path "$Rollback" -Value '' -Force
	Add-Content -Path "$Rollback" -Value "echo %DATE%-%TIME% Running $($SCCMClientPath)\\TSMBootstrap.exe to resume task sequence >> %WINDIR%\setuprollback.log" -Force
	Add-Content -Path "$Rollback" -Value "$($SCCMClientPath)\\TSMBootstrap.exe /env:Gina /configpath:$($SMSTSMDataPath) /bootcount:2 /reloadenv" -Force
	Add-Content -Path "$Rollback" -Value '' -Force
	Add-Content -Path "$Rollback" -Value 'IF %ERRORLEVEL% EQU -2147021886 (' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% ERRORLEVEL = %ERRORLEVEL%  >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% TSMBootstrap requested reboot >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Rebooting now >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'reg add HKLM\SYSTEM\Setup /v SetupShutdownRequired /t REG_DWORD /d 1 /f' -Force
	Add-Content -Path "$Rollback" -Value ') else (' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% ERRORLEVEL = %ERRORLEVEL%  >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% TSMBootstrap did not request reboot, resetting registry >> %WINDIR%\setuprollback.log' -Force
	Add-Content -Path "$Rollback" -Value 'reg add HKLM\SOFTWARE\Microsoft\CCM\CcmExec /v ProvisioningMode /t REG_SZ /d "false" /f' -Force
	Add-Content -Path "$Rollback" -Value 'reg add HKLM\SYSTEM\Setup /v SetupType /t REG_DWORD /d 0 /f' -Force
	Add-Content -Path "$Rollback" -Value 'reg add HKLM\SYSTEM\Setup /v CmdLine /t REG_SZ /d "" /f' -Force
	Add-Content -Path "$Rollback" -Value ')' -Force
	Add-Content -Path "$Rollback" -Value 'echo %DATE%-%TIME% Exiting setuprollback.cmd >> %WINDIR%\setuprollback.log' -Force
	
	# Setup Initial Registry Values for Upgrade
	REG ADD HKLM\SYSTEM\Setup /v SetupType /t REG_DWORD /d 2 /f # 0: Do nothing, 1: Run CmdLine then Reboot, 2: Run CmdLine then show login screen
	REG ADD HKLM\SYSTEM\Setup /v SetupShutdownRequired /t REG_DWORD /d 1 /f # 0: Shutdown Poweroff, 1: Shutdown Reboot, 2: Shutdown NoReboot
	REG ADD HKLM\SYSTEM\Setup /v CmdLine /t REG_SZ /d "$($Setup)" /f
	# OSDUpgradeOS.exe
	REG ADD HKLM\SOFTWARE\Microsoft\CCM\CcmExec /v ProvisioningMode /t REG_SZ /d "true" /f
	Set-Service CcmExec -StartupType Disabled
	Set-Service SMSTsMgr -StartupType Disabled 
}

This creates files similar to the SetupCompleteTemplate.cmd found in the CCM folder with the addition of putting the client in provision mode, disabling CcmExec & SmsTsMgr services. It will also then put everything back after the final reboot.

For the upgrade step, I then run:

%OSUpgrade01%\SETUP.EXE /ImageIndex 3 /auto Upgrade /quiet /noreboot /showoobe none /postoobe “%WINDIR%\CCM\SetupCompleteUpgrade.cmd” /postrollback “%WINDIR%\CCM\SetupRollbackUpgrade.cmd” /DynamicUpdate Disable /compat IgnoreWarning

This will then do an upgrade for Windows 10 Enterprise using the newly created SetupComplete files for post or rollback. Once it’s done all it can, I run a ‘Restart Computer’ so I can easily set the one time time-out depending if a user is present or not. Then it will be 20-30 minutes of upgrading and then on to Post-Processing.

*Tip: I keep the actual ‘Upgrade Operating System’ step there but disabled so the deployed task sequence is still available under ‘Operating Systems’ in Software Center instead of showing up under ‘Applications’.