Continuing PowerShell Scripts After Reboot - How to do it?
In PowerShell scripting, ensuring scripts continue after a reboot can be challenging, especially when managing configurations or updates that require a system restart. There are two primary strategies for local and remote execution environments to address this issue.
Let's dive into how you can make your PowerShell scripts pick up right where they left off after a reboot, whether you're working on your computer or handling tasks on remote machines.
Using Task Scheduler for Local Computers
To keep your PowerShell script running after a reboot on a local computer, use the Windows Task Scheduler.
This method sets up a task that starts after a restart, so you don't have to manually restart your script.
Let's dive into two practical examples of implementing the reboot-and-continue pattern with PowerShell, utilizing the Windows Task Scheduler.
Example 1: Run a Script Block After Reboot
In this example, we'll create a simple PowerShell script that does some initial actions and then sets up a scheduled task to execute a script block after the system reboots.
# Initial actions Write-Host "Performing initial actions before reboot..." # Command to run a script block upon reboot $scriptBlock = { Write-Host "This is the continuation after reboot." } # Convert script block to a Base64 encoded string to pass it to the scheduled task $encodedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($scriptBlock.ToString())) # Creating the scheduled task $action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument "-EncodedCommand $encodedCommand" $trigger = New-ScheduledTaskTrigger -AtStartup Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "ContinueAfterReboot" -Description "My task to continue script execution after reboot" # Restart the computer (uncomment in actual use) Restart-Computer
In this scenario, the PowerShell script handles the issue by first executing preliminary actions—these could range from system checks, application shutdowns, or preparation steps for an update. Then, it creates a scheduled task designed to execute a PowerShell script block which contains the commands or continuation logic needed to finalize the system's configuration after it reboots.
To achieve this, the script converts the PowerShell script block into a Base64 encoded string because the scheduled task's command line doesn't directly accept script blocks.
When the system starts up, the task triggers, launching PowerShell with the encoded script block as an argument, effectively resuming the script's execution right where you need it to.
Example 2: Run the Same or Another Script Based on a Registry Key
In the second example, the script checks for a registry key to determine if it's the first run or a continuation after a reboot.
- If it's the first run, it performs initial actions and schedules itself to run again after reboot.
- If it's continuing after a reboot, it skips the initial part and proceeds with the next actions.
# Check for the registry key to determine if this is the initial run or continuation if (Test-Path -Path "HKCU:\Software\Test\ISRun") { # This is a continuation after reboot Write-Host "Continuing with the next part of the script..." # Perform the next part of the script... # Clean up: Remove the registry key and scheduled task if no longer needed Remove-Item -Path "HKCU:\Software\Test\ISRun" Unregister-ScheduledTask -TaskName "ContinueAfterReboot" -Confirm:$false } else { # This is the initial run Write-Host "Performing initial actions..." # Set a registry key to indicate the script has run New-Item -Path "HKCU:\Software\Test" -Force New-ItemProperty -Path "HKCU:\Software\Test" -Name "ISRun" -Value "true" -PropertyType "String" -Force # Schedule this script to run after reboot $action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument "-File `"$PSScriptRoot\$(Split-Path -Path $MyInvocation.MyCommand.Path -Leaf)`"" $trigger = New-ScheduledTaskTrigger -AtStartup Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "ContinueAfterReboot" -Description "Task to rerun the script after reboot" # Restart the computer (uncomment in actual use) Restart-Computer }
This example addresses a common scenario where a script needs to run in two stages, with a reboot in between, without manual intervention to restart it. The challenge is ensuring that the script knows if it’s running for the first time or continuing after a reboot.
The solution is to use the Windows Registry as a marker or flag to track the script's execution state.
During the first run, the script performs its initial set of actions—these could include system diagnostics, pre-update tasks, or configurations that need to be applied before a reboot. It then creates a specific registry key (HKCU:\Software\Test\ISRun) to mark that the initial phase has been completed. Subsequently, it schedules itself (or another script) to run at the system's next startup.
After the reboot, the scheduled task starts the script again, which first checks for the registry key.
If the key is there, it knows the initial phase is done and moves on to the next tasks—post-reboot configurations, cleanup operations, or any finalization steps required to complete the task.
After these actions conclude, the script removes the registry key (and the scheduled task if necessary) to clean up and prevent it from running again on future reboots.
Using Restart-Computer for Remote Computer
For remote computers, it gets a bit easier with the Restart-Computer -Wait command. This command tells your script to wait until the computer has restarted before continuing.
Here's how to use it:
Restart-Computer -ComputerName "RemotePC1", "RemotePC2" -Wait -For PowerShell -Timeout 600 -Delay 2
Managing reboot and continue operations for remote computers can be done by using the Restart-Computer cmdlet, enhanced with the -Wait parameter. This parameter pauses the script's execution until the specified remote computers have completed their restart process.
However, it's important to note the limitations when applying this method to the local computer.
According to Microsoft's documentation, the -Wait parameter does not apply when restarting the local machine itself. If you include both remote and local computer names in the ComputerName parameter, the cmdlet issues a non-terminating error for the local machine while appropriately waiting for the remote machines to reboot.
This command restarts RemotePC1 and RemotePC2 and waits up to 600 seconds (10 minutes) for them to restart and continue running the script, checking every 2 seconds to see if they're back online.
Conclusion
By using these methods, you can automate tasks that need a restart without manual intervention.
Whether you're deploying software updates or making system changes, these techniques ensure your PowerShell scripts continue execution seamlessly after a reboot, making the process smoother and more efficient.