Rebooting a device can be a source of frustration for end users. Deep down they know it will clear up RAM and improve their device’s performance, but they just can’t bring themselves to rip off the bandaid.
That’s where this script comes in.
Running the script will inform your end users that in order to apply various patches and updates, they must reboot their device. They will then be given the choice whether they want to restart their device immediately, postpone the restart for one hour, or cancel altogether. If they don’t make a selection, the device will automatically restart in 15 minutes, with a countdown timer to let them know how much time they have left until shutdown. This gives them a chance to mentally prepare and save any important files.
The script uses Windows forms to display the notification, and the content is fully customizable. You can add your company name, change the message, and alter the button options (if you’re feeling particularly mischievous, you can even remove the cancel button). You can also adjust the time frame for automatic restart or postponing updates. Just be sure not to let your end users procrastinate for too long!
Das Skript:
Atera garantiert nicht die Integrität, die Verfügbarkeit, die Sicherheit, die Virenfreiheit, die Sicherheit, die Rechtmäßigkeit, die Nichtverletzung, den Status der Rechte oder die Funktionalität der Skripte. Die Nutzung der gemeinsam genutzten Skripte erfolgt auf eigenes Risiko. Die Skripte werden " wie sie sind " zur Verfügung gestellt.*
?[void][Reflection.Assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][Reflection.Assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][Reflection.Assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
function Main {
Param ([String]$Commandline)
if((Call-MainForm_psf) -eq 'OK')
{
}
$global:ExitCode = 0
}
function Call-MainForm_psf
{
[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[System.Windows.Forms.Application]::EnableVisualStyles()
$MainForm = New-Object 'System.Windows.Forms.Form'
$panel2 = New-Object 'System.Windows.Forms.Panel'
$ButtonCancel = New-Object 'System.Windows.Forms.Button'
$ButtonPostpone1Hour = New-Object 'System.Windows.Forms.Button'
$ButtonRestartNow = New-Object 'System.Windows.Forms.Button'
$panel1 = New-Object 'System.Windows.Forms.Panel'
$labelITSystemsMaintenance = New-Object 'System.Windows.Forms.Label'
$labelSecondsLeftToRestart = New-Object 'System.Windows.Forms.Label'
$labelTime = New-Object 'System.Windows.Forms.Label'
$labelInOrderToApplySecuri = New-Object 'System.Windows.Forms.Label'
$timerUpdate = New-Object 'System.Windows.Forms.Timer'
$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
$TotalTime = 900
$MainForm_Load={
$labelTime.Text = "{0:D2}" -f $TotalTime
$script:StartTime = (Get-Date).AddSeconds($TotalTime)
$timerUpdate.Start()
}
$timerUpdate_Tick={
[TimeSpan]$span = $script:StartTime - (Get-Date)
$hours = "{0:00}" -f $span.Hours
$mins = "{0:00}" -f $span.Minutes
$secs = "{0:00}" -f $span.Seconds
$labelTime.Text = "{0}:{1}:{2}" -f $hours, $mins, $secs
$timerUpdate.Start()
if ($span.TotalSeconds -le 0)
{
$timerUpdate.Stop()
Restart-Computer -Force
}
}
$ButtonRestartNow_Click = {
Restart-Computer -Force
}
$ButtonPostpone1Hour_Click={
shutdown -r -t 3600
$MainForm.Close()
}
$ButtonCancel_Click={
$MainForm.Close()
}
$labelITSystemsMaintenance_Click={
}
$panel2_Paint=[System.Windows.Forms.PaintEventHandler]{
}
$labelTime_Click={
}
$Form_StateCorrection_Load=
{
$MainForm.WindowState = $InitialFormWindowState
}
$Form_StoreValues_Closing=
{
}
$Form_Cleanup_FormClosed=
{
try
{
$ButtonCancel.remove_Click($buttonCancel_Click)
$ButtonPostpone1Hour.remove_Click($ButtonPostpone1Hour_Click)
$ButtonRestartNow.remove_Click($ButtonRestartNow_Click)
$panel2.remove_Paint($panel2_Paint)
$labelITSystemsMaintenance.remove_Click($labelITSystemsMaintenance_Click)
$labelTime.remove_Click($labelTime_Click)
$MainForm.remove_Load($MainForm_Load)
$timerUpdate.remove_Tick($timerUpdate_Tick)
$MainForm.remove_Load($Form_StateCorrection_Load)
$MainForm.remove_Closing($Form_StoreValues_Closing)
$MainForm.remove_FormClosed($Form_Cleanup_FormClosed)
}
catch [Exception]
{ }
}
$MainForm.SuspendLayout()
$panel2.SuspendLayout()
$panel1.SuspendLayout()
$MainForm.Controls.Add($panel2)
$MainForm.Controls.Add($panel1)
$MainForm.Controls.Add($labelSecondsLeftToRestart)
$MainForm.Controls.Add($labelTime)
$MainForm.Controls.Add($labelInOrderToApplySecuri)
$MainForm.AutoScaleDimensions = '6, 13'
$MainForm.AutoScaleMode = 'Font'
$MainForm.BackColor = 'White'
$MainForm.ClientSize = '373, 279'
$MainForm.MaximizeBox = $False
$MainForm.MinimizeBox = $False
$MainForm.Name = 'MainForm'
$MainForm.ShowIcon = $False
$MainForm.ShowInTaskbar = $False
$MainForm.StartPosition = 'CenterScreen'
$MainForm.Text = 'Your Company | IT Systems Maintenance'
$MainForm.TopMost = $True
$MainForm.add_Load($MainForm_Load)
$panel2.Controls.Add($ButtonCancel)
$panel2.Controls.Add($ButtonPostpone1Hour)
$panel2.Controls.Add($ButtonRestartNow)
$panel2.BackColor = 'ScrollBar'
$panel2.Location = '0, 205'
$panel2.Name = 'panel2'
$panel2.Size = '378, 80'
$panel2.TabIndex = 9
$panel2.add_Paint($panel2_Paint)
$ButtonCancel.Location = '250, 17'
$ButtonCancel.Name = 'ButtonCancel'
$ButtonCancel.Size = '77, 45'
$ButtonCancel.TabIndex = 7
$ButtonCancel.Text = 'Cancel'
$ButtonCancel.UseVisualStyleBackColor = $True
$ButtonCancel.add_Click($buttonCancel_Click)
$ButtonPostpone1Hour.Font = 'Microsoft Sans Serif, 8.25pt, style=Bold'
$ButtonPostpone1Hour.Location = '139, 17'
$ButtonPostpone1Hour.Name = 'ButtonPostpone1Hour'
$ButtonPostpone1Hour.Size = '105, 45'
$ButtonPostpone1Hour.TabIndex = 6
$ButtonPostpone1Hour.Text = 'Postpone for 1 Hour'
$ButtonPostpone1Hour.UseVisualStyleBackColor = $True
$ButtonPostpone1Hour.add_Click($ButtonPostpone1Hour_Click)
$ButtonRestartNow.Font = 'Microsoft Sans Serif, 8.25pt, style=Bold'
$ButtonRestartNow.ForeColor = 'DarkRed'
$ButtonRestartNow.Location = '42, 17'
$ButtonRestartNow.Name = 'ButtonRestartNow'
$ButtonRestartNow.Size = '91, 45'
$ButtonRestartNow.TabIndex = 0
$ButtonRestartNow.Text = 'Restart Now'
$ButtonRestartNow.UseVisualStyleBackColor = $True
$ButtonRestartNow.add_Click($ButtonRestartNow_Click)
$panel1.Controls.Add($labelITSystemsMaintenance)
$panel1.BackColor = '0, 114, 198'
$panel1.Location = '0, 0'
$panel1.Name = 'panel1'
$panel1.Size = '375, 67'
$panel1.TabIndex = 8
$labelITSystemsMaintenance.Font = 'Microsoft Sans Serif, 14.25pt'
$labelITSystemsMaintenance.ForeColor = 'White'
$labelITSystemsMaintenance.Location = '11, 18'
$labelITSystemsMaintenance.Name = 'labelITSystemsMaintenance'
$labelITSystemsMaintenance.Size = '269, 23'
$labelITSystemsMaintenance.TabIndex = 1
$labelITSystemsMaintenance.Text = 'Scheduled Maintenance'
$labelITSystemsMaintenance.TextAlign = 'MiddleLeft'
$labelITSystemsMaintenance.add_Click($labelITSystemsMaintenance_Click)
$labelSecondsLeftToRestart.AutoSize = $True
$labelSecondsLeftToRestart.Font = 'Microsoft Sans Serif, 9pt, style=Bold'
$labelSecondsLeftToRestart.Location = '87, 176'
$labelSecondsLeftToRestart.Name = 'labelSecondsLeftToRestart'
$labelSecondsLeftToRestart.Size = '155, 15'
$labelSecondsLeftToRestart.TabIndex = 5
$labelSecondsLeftToRestart.Text = 'Time left to restart :'
$labelTime.AutoSize = $True
$labelTime.Font = 'Microsoft Sans Serif, 9pt, style=Bold'
$labelTime.ForeColor = '192, 0, 0'
$labelTime.Location = '237, 176'
$labelTime.Name = 'labelTime'
$labelTime.Size = '43, 15'
$labelTime.TabIndex = 3
$labelTime.Text = '00:60'
$labelTime.TextAlign = 'MiddleCenter'
$labelTime.add_Click($labelTime_Click)
$labelInOrderToApplySecuri.Font = 'Microsoft Sans Serif, 9pt'
$labelInOrderToApplySecuri.Location = '12, 84'
$labelInOrderToApplySecuri.Name = 'labelInOrderToApplySecuri'
$labelInOrderToApplySecuri.Size = '350, 83'
$labelInOrderToApplySecuri.TabIndex = 2
$labelInOrderToApplySecuri.Text = 'In order to apply security patches and updates for your system, your computer must be restarted.
Please save all your files now to prevent data loss.'
$timerUpdate.add_Tick($timerUpdate_Tick)
$panel1.ResumeLayout()
$panel2.ResumeLayout()
$MainForm.ResumeLayout()
$InitialFormWindowState = $MainForm.WindowState
$MainForm.add_Load($Form_StateCorrection_Load)
$MainForm.add_FormClosed($Form_Cleanup_FormClosed)
$MainForm.add_Closing($Form_StoreValues_Closing)
return $MainForm.ShowDialog()
}
Main ($CommandLine)
Gehen Daten von laufenden Programmen verloren, wenn das Gerät neu gestartet wird?
Wenn Sie das Gerät sofort neu starten, kann dies zu Datenverlusten führen. Um dies zu verhindern, enthält die Standardmeldung, die dem Endbenutzer bei der Ausführung des Skripts angezeigt wird, eine Erinnerung, seine Dateien zu speichern. Es wird empfohlen, diese Zeile in der angezeigten Meldung beizubehalten, um sicherzustellen, dass die Endbenutzer sich der Gefahr eines Datenverlusts bewusst sind und Maßnahmen ergreifen können, um diesen zu verhindern.
Werden die Nutzer an den Neustart des Geräts erinnert, wenn sie die Option "Verschieben" gewählt haben?
Ja, die Benutzer werden durch eine Windows-Anmeldeerinnerung, die in der unteren rechten Ecke ihres Bildschirms angezeigt wird, über den genauen Zeitpunkt des Herunterfahrens informiert. Wenn der Zeitrahmen für die Verschiebung von Updates geändert wird, wird dies im Erinnerungsdialog angezeigt. Außerdem wird 10 Minuten vor dem Neustart eine Popup-Erinnerung angezeigt.
Kann mein Endbenutzer einen geplanten Neustart abbrechen?
Wenn ein Endbenutzer über einen geplanten Neustart benachrichtigt wird, diesen aber abbrechen möchte, kann er dies tun, indem er das Ausführungsfenster (STRG+R) aufruft und “shutdown -a” gefolgt von der Eingabetaste eingibt. Dadurch wird der Neustart abgebrochen.
Technische Hinweise:
- Das Skript ist eine .ps1-Datei.
- Um den Zeitrahmen für den automatischen Neustart oder die Verschiebung von Aktualisierungen zu ändern, können Sie die Anzahl der Sekunden in den Zeilen 35 bzw. 62 des Skripts aktualisieren. Der Standardtimer ist auf 15 Minuten bzw. 900 Sekunden eingestellt.