I'm trying to develop a script to pop up a messagebox to a user who has the computer connected at a certain hour of the day. If the user confirms he's using the computer by pressing a button of the messagebox then the process stops. If the user does not press anything for 30 m means he's not at the computer, and we shut down the computer.
I can pop up the messagebox with the message, but how can I check if the button has been pressed or give it a wait 30 m and then if nothing happens, do something else?
CodePudding user response:
You can use the Wscript.Shell
COM object's .Popup()
method, which supports specifying a timeout after which the dialog (message box) is automatically closed.
In the simplest case:
# Show a message box with an OK button that auto-closes
# after 3 seconds.
# Return value is:
# -1, if the dialog auto-closes
# 1 if the user pressed OK
$response =
(New-Object -ComObject WScript.Shell).Popup(
'I will close in 3 seconds',
3, # timeout in seconds
'Title',
48 # exclamation-point icon; OK button by default
)
if ($response -eq -1) { 'Auto-closed.' } else { 'User pressed OK.' }
A complete example that shows a dialog with OK and Cancel buttons: if the dialog auto-closes or the user presses OK, the script continues; otherwise, processing is aborted:
# How long to display the dialog before it closes automatically.
$timeoutSecs = 30 * 60 # 30 minutes.
# Translate this into the time of day, to show to the user.
$timeoutTimeOfDay = (Get-Date).AddSeconds($timeoutSecs).ToString('T')
# Put up a message box with a timeout and OK / Cancel buttons.
$response =
(New-Object -ComObject WScript.Shell).Popup(
@"
Your computer will shut down at $timeoutTimeOfDay.
Press OK to shut down now, or Cancel to cancel the shutdown.
"@,
$timeoutSecs,
'Pending shutdown',
49 # 48 1 == exclamation-point icon OK / Cancel buttons
)
if ($response -eq 2) { # Cancel pressed.
Write-Warning 'Shutdown aborted by user request.'
exit 2
}
# OK pressed ($response -eq 1) or timed out ($response -eq -1),
# proceed with shutdown.
'Shutting down...'
# Restart-Computer -Force
Note:
The above dialog is statically shows only the time of day at which the shutdown will be initiated.
If you want a realtime countdown of the seconds remaining, more work is needed: see Fitzgery's helpful answer.
CodePudding user response:
Here's that Function that I mentioned in my comment
Function Invoke-RestartTimer {
<#
.SYNOPSIS
Restart Computer After Timer reaches 0
.DESCRIPTION
Pops-Up a GUI Window that Counts Down Seconds until the Computer restarts. It also has buttons to either Restart Now or Cancel the Restart.
If the Restart is Cancelled it will write to the host with Write-Warning that the Restart was cancelled by the Current User.
.PARAMETER Seconds
Identifies the Amount of Seconds the Timer will countdown from
.EXAMPLE
Restart-Computer -Seconds 30
.NOTES
Multi-use Advanced Function for performing a Visual Countdown Restart.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[Int32]$Seconds = "15"
)
#Builds Assemblies for Custom Forms used in the function
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
#Identifies logged on user for if restart is cancelled
$CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
#Adds 1 to the identified time to ensure restart happens at 0 seconds and not -1 seconds.
#$Seconds
#Builds Form
$RestartForm = New-Object System.Windows.Forms.Form
$RestartForm.StartPosition = "CenterScreen"
$RestartForm.Size = New-Object System.Drawing.Size(300,150)
$RestartForm.Text = "Restart Window"
$RestartForm.AllowTransparency = $true
$RestartForm.BackColor = "LightGray"
$RestartForm.FormBorderStyle = "Fixed3D"
#Builds Text Label
$Script:TimerLabel = New-Object System.Windows.Forms.Label
$TimerLabel.AutoSize = $true
$TimerLabel.Font = "Microsoft Lucida Console,10"
$RestartForm.Controls.Add($TimerLabel)
#Builds Timer
$Timer = New-Object System.Windows.Forms.Timer
$Timer.Interval = 1000 #1 second countdown, in milliseconds
$script:CountDown = $Seconds #seconds to countdown from
$Timer.add_Tick({
$Script:TimerLabel.Text = "
The Computer will restart in $CountDown seconds.
Press the Restart Button to Restart Now."
$Script:CountDown--
If($CountDown -eq "-2"){#Needs to be 2 below wanted value. i.e 0 = -2
$Timer.Stop()
$RestartForm.Close()
Restart-Computer -Force
}
})
$Timer.Start()
#Builds a Restart Button
$RestartButton = New-Object System.Windows.Forms.Button
$RestartButton.Text = "Restart"
$RestartButton.FlatStyle = "Popup"
$RestartButton.Location = New-Object System.Drawing.Size(50,80)
$RestartButton.Size = New-Object System.Drawing.Size(80,23)
$RestartButton.Font = "Microsoft Lucida Console,10"
$RestartButton.Add_Click({
$Timer.Stop()
$RestartForm.Close()
Restart-Computer -Force
})
$RestartForm.Controls.Add($RestartButton)
#Builds a Cancel Button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Text = "Cancel"
$CancelButton.FlatStyle = "Popup"
$CancelButton.Location = New-Object System.Drawing.Size(150,80)
$CancelButton.Size = New-Object System.Drawing.Size(80,23)
$CancelButton.Font = "Microsoft Lucida Console,10"
$CancelButton.Add_Click({
$Timer.Stop()
$RestartForm.Close()
Write-Warning "Restart was aborted by $CurrentUser"
})
$RestartForm.Controls.Add($CancelButton)
[void]$RestartForm.ShowDialog()
}