In our previous blog posts, we explored different approaches to migrating to Windows 11: using SCCM, through XOAP, via GPOs and registry keys and Windows Update in Settings. In this post, we’ll walk you through yet another method – deploying the Windows 11 upgrade package using our PowerShell App Deployment Toolkit (download it here for free).
Use PSADT to migrate from Windows 10 to Windows 11
To get started, extract the contents of your Windows 11 ISO file and include them in your PSADT package. Then, you’ll use the setup.exe file from the extracted ISO along with specific command-line parameters to upgrade from Windows 10 to Windows 11.
Once you’ve got your source file ready, it’s time to modify the “Deploy-Application.ps1” script. In the pre-installation part, it will check if a scheduled task exists and delete it (in case of failures/reruns).
#### (Pre-Install) Delete Scheduled Task -------------------------------------------->
$DELTaskName = 'Win11Upgrade'
# Check if the task exists
$DELTaskExists = Get-ScheduledTask -TaskName $DELTaskName -ErrorAction SilentlyContinue
if ($DELTaskExists) {
# Delete the task
Unregister-ScheduledTask -TaskName $DELTaskName -Confirm:$false
Write-Output "(Pre-Install) Task '$DELTaskName' has been deleted."
} else {
Write-Output "(Pre-Install) Task '$DELTaskName' does not exist. Moving on to Installation"
}
In the installation part, a scheduled task will be created and started. While loop is used to check if the task is still running after it was started.
###># CREATE SCHEDULED TASK -------------------------------------------------------->
$STExecutable = "$dirfiles\ISO\Setup.exe"
$STArguments = "/Auto Upgrade /EULA accept /NoReboot"
$STTaskName = "Win11Upgrade"
$STTriggerTime = (Get-Date).AddSeconds(15)
$STPriority = 4
$STTrigger = New-ScheduledTaskTrigger -Once -At $STTriggerTime
$STSettings = New-ScheduledTaskSettingsSet -StartWhenAvailable -Priority $STPriority -RunOnlyIfNetworkAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
# Create a new scheduled task action
$STAction = New-ScheduledTaskAction -Execute $STExecutable -Argument $STArguments -WorkingDirectory (Split-Path $STExecutable)
# Create a new scheduled task principal for the SYSTEM account
$STPrincipal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
# Create and register the new scheduled task
$STTask = New-ScheduledTask -Action $STAction -Trigger $STTrigger -Settings $STSettings -Principal $STPrincipal
Register-ScheduledTask -TaskName $STTaskName -InputObject $STTask
#### KICK OFF SCHEDULED TASK ------------------------------------------------------>
Start-Sleep 10
Start-ScheduledTask -TaskName "Win11Upgrade"
#### MONITOR SCHEDULED TASK ------------------------------------------------------->
$STTaskName = "Win11Upgrade"
# Loop until the task is no longer running
while ((Get-ScheduledTask -TaskName $STTaskName).State -eq "Running")
{
# Get task information
$taskInfo = Get-ScheduledTaskInfo -TaskName $STTaskName
# Verify if the task is being run by SYSTEM
if ((Get-ScheduledTask -TaskName $STTaskName).Principal.UserId -eq "SYSTEM")
{
# Write to the output
Write-Output "$STTaskName is still running as SYSTEM"
}
else
{
Write-Output "$STTaskName is still running, but not as SYSTEM"
}
# Wait for 10 seconds before checking again
Start-Sleep -Seconds 10
}
Write-Output "$STTaskName has finished running"
 In the post-installation part, created scheduled task is deleted.
#### (Post-Install) Delete Scheduled Task -------------------------------------------->
$DELTaskName = "Win11Upgrade"
# Check if the task exists
$DELTaskExists = Get-ScheduledTask -TaskName $DELTaskName -ErrorAction SilentlyContinue
if ($DELTaskExists) {
# Delete the task
Unregister-ScheduledTask -TaskName $DELTaskName -Confirm:$false
Write-Output "(Post-Install) Task '$DELTaskName' has been deleted."
} else {
Write-Output "(Post-Install) Task '$DELTaskName' does not exist."
}
There are a couple of options to consider if you want to expand on this package:
- Add Windows 11 prerequisites check
- Expand it with PSADT functions like:
– Show-InstallationWelcome
– Show-InstallationProgress
– Show-InstallationRestartPrompt - Adjust available scheduled task options:
– RunOnlyIfNetworkAvailable
– AllowStartIfOnBatteries
– DontStopIfGoingOnBatteries - Add other parameters to setup.exe run (for example “/Product Server” as a workaround for the prerequisites check)
You're good to go!
Upgrading to Windows 11 with PSADT is a flexible option if you want more control over the process. With a few script tweaks, you can handle the upgrade from start to finish.