Example Code > PowerShell Scripts > PowerShell Automated Reboot |
The following PowerShell script creates a dialog window which performs an automated device reboot after a pre-specified timeout period. The dialog window has buttons for Cancel and Reboot Now. If the users selects Cancel the script terminates with immediate effect. Should the user select Reboot Now the device will reboot immediately. If no action is taken by the user the code contains a countdown timer object which will countdown and then reboot the device automatically once the timeout period has been met.
The two important variables are $nTimeout which contains the timeout period in seconds and $debug_mode which can be set to $true when testing so that no actual reboot takes place.
The routine is designed to be called as a Windows scheduled task and can be used to automatically reboot workstations at a specified day and time. This is useful for devices that are left on permanently and can often go for weeks or even months without a shutdown or restart.
The .ps1 code is presented below; The code has been tested and works on Windows 10/11.
#----------------------------------------------------------------------------# # Program Copyright : Mike Wilcock. # Program Name : device_reboot.ps1. #----------------------------------------------------------------------------# # Program Created : 23rd May 2023. # Program Code Type : PowerShell Script (version 5.1.22621.436). # Author : Michael Wilcock, IT Technician. #----------------------------------------------------------------------------# # Version : 2.10 #----------------------------------------------------------------------------# # Purpose : Reboot PC with user confirmation dialog box and timeout. #----------------------------------------------------------------------------# # Timeout in seconds. $nTimeout = 30 # If set to true the reboot will not happen. Set to false for production. $debug_mode = $true # Countdown timer. Variable MUST be global in scope. $global:nCountdown = $nTimeout #----------------------------------------------------------------------------# # Elegantly perform reboot. #----------------------------------------------------------------------------# # Notes: Function is called by the timer object and the reboot button click event. # # If memvar $debug_mode is $true perform a simulated reboot #----------------------------------------------------------------------------# function close_and_reboot() { # Simulate reboot for testing. if($debug_mode -eq $true) { Restart-Computer -whatIf } # Production. else { Restart-Computer } # Close dialog window. $oDlg.Close() } #----------------------------------------------------------------------------# # Update countdown timer label. #----------------------------------------------------------------------------# # Notes: Function is called every second by the timer object. Uses globaly # scoped variable to store the seconds left until reboot happens. #----------------------------------------------------------------------------# function updCountdown() { # Decrement countdown timer global variable. $global:nCountdown-- # Update countdown label. $lbl_countdown.text = "Time To Restart: " + $global:nCountdown } #----------------------------------------------------------------------------# # Main code. Create dialog window, timer object and form components. #----------------------------------------------------------------------------# # Load windows forms class. Add-Type -assembly System.Windows.Forms $cMessage = "Device: " + $env:computername + " Requires A Reboot`n`nPlease select Cancel to delay the restart until further notice.`n`nIf no selection is made the device will restart after $nTimeout seconds!" $cTitle = "[" + $env:computername + "] - " + "Automatic Device Restart" $CenterScreen = [System.Windows.Forms.FormStartPosition]::CenterScreen; # Button row in pixels. $nBtnRow = 170 # Create our dialog window. $oDlg = New-Object System.Windows.Forms.Form $oDlg.Text = $cTitle $oDlg.Width = 475 $oDlg.Height = 235 $oDlg.FormBorderStyle = 'Fixed3D' $oDlg.MaximizeBox = $false $oDlg.MinimizeBox = $false $oDlg.StartPosition = $CenterScreen; $oDlg.AutoSize = $true # Create a timer. $timer_reboot = New-Object System.Windows.Forms.Timer $timer_reboot.Interval = $nTimeout * 1000 # Set up the event handler for the timer. $timer_reboot.Add_Tick({close_and_reboot}) # Panel object. $panel = New-Object System.Windows.Forms.Panel $panel.Left = 0 $panel.Top = 0 $panel.Width = $oDlg.Width $panel.Height = 61 $panel.BackColor = '255, 255, 255' $panel.Dock = "top" # Add panel to our form. $oDlg.Controls.Add($panel) # Add an image to the form using Base64. $base64ImageString = "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" $imageBytes = [Convert]::FromBase64String($base64ImageString) $ms = New-Object IO.MemoryStream($imageBytes, 0, $imageBytes.Length) $ms.Write($imageBytes, 0, $imageBytes.Length); $nhs_logo = [System.Drawing.Image]::FromStream($ms, $true) # picturebox object. $pictureBox = new-object Windows.Forms.PictureBox $pictureBox.Width = $nhs_logo.Size.Width; $pictureBox.Height = $nhs_logo.Size.Height; $pictureBox.Location = New-Object System.Drawing.Size(360,0) $pictureBox.Image = $nhs_logo; # Add picturebox to our form. $oDlg.Controls.Add($pictureBox) # User message label. $lbl_message = New-Object System.Windows.Forms.Label $lbl_message.Text = $cMessage $lbl_message.Location = New-Object System.Drawing.Point(10,80) $lbl_message.AutoSize = $true # Add label to our form. $oDlg.Controls.Add($lbl_message) # Countdown timer label. $lbl_countdown = New-Object System.Windows.Forms.Label $lbl_countdown.Text = "Time To Restart: " + $nCountdown $lbl_countdown.Location = New-Object System.Drawing.Point(10, $nBtnRow) $lbl_countdown.ForeColor = "red" $lbl_countdown.AutoSize = $true # Add label to our form. $oDlg.Controls.Add($lbl_countdown) # Create a timer. $timer_countdown = New-Object System.Windows.Forms.Timer $timer_countdown.Interval = 1000 # Set up the event handler for the timer. $timer_countdown.Add_Tick({updCountdown}) # Reboot button. $btn_reboot = New-Object System.Windows.Forms.Button $btn_reboot.Location = New-Object System.Drawing.Size(355, $nBtnRow) $btn_reboot.Size = New-Object System.Drawing.Size(100, 23) $btn_reboot.Text = "REBOOT NOW" # Add button to our form. $oDlg.Controls.Add($btn_reboot) # Capture click event. $btn_reboot.Add_Click({close_and_reboot}) # Cancel button. $btn_cancel = New-Object System.Windows.Forms.Button $btn_cancel.Location = New-Object System.Drawing.Size(255, $nBtnRow) $btn_cancel.Size = New-Object System.Drawing.Size(100, 23) $btn_cancel.Text = "Cancel" $oDlg.Controls.Add($btn_cancel) # Add button to our form. $btn_cancel.Add_Click({$oDlg.Close()}) # IMPORTANT. Order items for correct display. $oDlg.Controls.SetChildIndex($panel, 1) # Start both timers. $timer_reboot.Start() $timer_countdown.Start() # Let's do this thing! $oDlg.ShowDialog() # Dispose (stop) the timer. Doing this here instead of in the tick # event handler ensures that the timer is stopped even when the form # was closed by the user. $timer_reboot.Dispose() $timer_countdown.Dispose() # Dispose the form and its controls. Skip, if you want to redisplay the form later. $oDlg.Dispose()
© Mike Wilcock, 2025.