For various (silly) reasons our office has a policy disabling the shutdown & restart buttons on our Windows 7 machines. I am a fan of restarting and shutting down the computer, so thought I should make some shortcuts to allow users to do themselves easily.
It’s easy to restart/ shutdown – just use the shutdown
command with the /r
or /s
switches, or use the Restart-Computer
or Stop-Computer
cmdlets. But I can’t expect users to do that, so a basic GUI is necessary.
Here’s a script I created:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $objForm = New-Object System.Windows.Forms.Form $objForm.Text = "Shutdown | Restart" $objForm.Size = New-Object System.Drawing.Size(300,300) $objForm.StartPosition = "CenterScreen" $objForm.FormBorderStyle = "FixedSingle" $objForm.KeyPreview = $True $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") {$objForm.Close()}}) $SButton = New-Object System.Windows.Forms.Button $SButton.Location = New-Object System.Drawing.Size(15,220) $SButton.Size = New-Object System.Drawing.Size(75,25) $SButton.Text = "Shutdown" $SButton.Add_Click({Stop-Computer -Force}) $objForm.Controls.Add($SButton) $RButton = New-Object System.Windows.Forms.Button $RButton.Location = New-Object System.Drawing.Size(110,220) $RButton.Size = New-Object System.Drawing.Size(75,25) $RButton.Text = "Restart" $RButton.Add_Click({Restart-Computer -Force}) $objForm.Controls.Add($RButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Size(205,220) $CancelButton.Size = New-Object System.Drawing.Size(75,25) $CancelButton.Text = "Cancel" $CancelButton.Add_Click({$objForm.Close()}) $objForm.Controls.Add($CancelButton) $outlook = @(Get-Process | ?{ $_.Name -eq "outlook" }).Count $word = @(Get-Process | ?{ $_.Name -eq "winword" }).Count $objLabel = New-Object System.Windows.Forms.Label $objLabel.Location = New-Object System.Drawing.Size(10,20) $objLabel.Size = New-Object System.Drawing.Size(280,120) $objLabel.Text = "Please ensure you have saved your work before proceeding.`n`nYou currently have $outlook Outlook and $word Word windows open." $objForm.Controls.Add($objLabel) $objForm.Topmost = $True $objForm.Add_Shown({$objForm.Activate()}) [void] $objForm.ShowDialog() |
I must mention that I have no clue designing GUIs with PowerShell. The script is mostly a copy-paste of this with some changes by me (like increasing the height of the box, adding three buttons, checking whether any Outlook/ Word processes are running, etc). The code’s pretty intuitive anyways. Here’s a screenshot of what you get:
I’d suggest placing the script in a location like c:\windows\system32
and creating a shortcut to it. Here’s the shortcut target I used:
1 |
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden -noprofile -nologo -noninteractive -file "c:\windows\system32\shutdown-restart.ps1" -ExecutionPolicy RemoteSigned |
It launches a PowerShell process, passes it the script, doesn’t load the profile (-noprofile
), doesn’t show the copyright notice (-nologo
), hides the window (-windowstyle hidden
), doesn’t show a prompt to the user (-noninteractive
), and sets the execution policy for that session to RemoteSigned
(needed for the script to be executed).
I would suggest putting the shortcut in c:\ProgramData\Microsoft\Windows\Start Menu\Programs
so users can find it/ search for in their Start menu.
Update: If you want the default selected button to be “Cancel” instead of “Shutdown” (as is the case above) move the “Cancel” block above the “Shutdown” block. The order of buttons will still be the same as they are decided by the Location
property of each object, but since the “Cancel” block is first that will be selected as the default button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $objForm = New-Object System.Windows.Forms.Form $objForm.Text = "Shutdown | Restart" $objForm.Size = New-Object System.Drawing.Size(300,300) $objForm.StartPosition = "CenterScreen" $objForm.FormBorderStyle = "FixedSingle" $objForm.KeyPreview = $True $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") {$objForm.Close()}}) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Size(205,220) $CancelButton.Size = New-Object System.Drawing.Size(75,25) $CancelButton.Text = "Cancel" $CancelButton.Add_Click({$objForm.Close()}) $objForm.Controls.Add($CancelButton) $SButton = New-Object System.Windows.Forms.Button $SButton.Location = New-Object System.Drawing.Size(15,220) $SButton.Size = New-Object System.Drawing.Size(75,25) $SButton.Text = "Shutdown" $SButton.Add_Click({Stop-Computer -Force}) $objForm.Controls.Add($SButton) $RButton = New-Object System.Windows.Forms.Button $RButton.Location = New-Object System.Drawing.Size(110,220) $RButton.Size = New-Object System.Drawing.Size(75,25) $RButton.Text = "Restart" $RButton.Add_Click({Restart-Computer -Force}) $objForm.Controls.Add($RButton) $outlook = @(Get-Process | ?{ $_.Name -eq "outlook" }).Count $word = @(Get-Process | ?{ $_.Name -eq "winword" }).Count $objLabel = New-Object System.Windows.Forms.Label $objLabel.Location = New-Object System.Drawing.Size(10,20) $objLabel.Size = New-Object System.Drawing.Size(280,120) $objLabel.Text = "Please ensure you have saved your work before proceeding.`n`nYou currently have $outlook Outlook and $word Word windows open." $objForm.Controls.Add($objLabel) $objForm.Topmost = $True $objForm.Add_Shown({$objForm.Activate()}) [void] $objForm.ShowDialog() |