679 lines
27 KiB
PowerShell
679 lines
27 KiB
PowerShell
<#
|
|
|
|
.SYNOPSIS
|
|
Provides friendly messages reminding a user to restart their computer based on events that require it.
|
|
|
|
.DESCRIPTION
|
|
The Set-RebootSchedule script is called from any computer management software to notify a user of a required restart.
|
|
This script accepts several different parameters which change the messages displayed to the user.
|
|
Some logic is used when determining the best time to remind the user to restart.
|
|
|
|
.PARAMETER SysPerf
|
|
The -SysPerf parameter will remind the user to restart due to system performance.
|
|
This parameter should be called if the computer has had consistently high memory usage, recurring application hangs, or stuck processes.
|
|
If this parameter is used it will simply tell the user that a restart is needed to improve overall stability.
|
|
|
|
.PARAMETER OSUpdate
|
|
The -OSUpdate parameter will remind the user to restart due to operating system updates.
|
|
|
|
.PARAMETER Uptime
|
|
The -Uptime parameter will remind the user to restart due to long uptimes.
|
|
This script does not define the length of time the computer has been on, but will display the number of days to the end user.
|
|
If the computer has been on for 10 days and this parameter is used, it will tell the user this computer has been on for 10 days.
|
|
|
|
.PARAMETER AllowMinimize
|
|
The -AllowMinimize parameter will let the prompts and reminders be minimized by the user.
|
|
By default, the user is not allowed to minimize the window.
|
|
|
|
.PARAMETER Override
|
|
The -Override parameter is used with either the -OSUpdate or -Uptime parameters.
|
|
This parameter will override the priority of the existing reminder schedule and overwrite any existing schedule with the one set when -Override is called.
|
|
See the NOTES section for additional information on schedule priorities.
|
|
|
|
.PARAMETER Remove
|
|
The -Remove parameter will simply delete any scheduled restart reminder.
|
|
|
|
.PARAMETER Task
|
|
The -Task parameter will allow this script to run without scheduling a task. This switch is called when this task creates a scheduled task of itself.
|
|
|
|
.EXAMPLE
|
|
Set-RebootSchedule -SysPerf
|
|
Prompt the user to restart because you've seen problems in multiple areas of the computer.
|
|
|
|
.EXAMPLE
|
|
Set-RebootSchedule -OSUpdate
|
|
Prompt the user to restart because Windows was recently updated.
|
|
|
|
.EXAMPLE
|
|
Set-RebootSchedule -Uptime
|
|
Prompt the user to restart because the computer has been up for a long time.
|
|
|
|
.EXAMPLE
|
|
Set-RebootSchedule -OSUpdate -Override
|
|
Prompt the user to restart because Windows was recently updated, overwriting any existing reminder schedule.
|
|
|
|
.EXAMPLE
|
|
Set-RebootSchedule -Uptime -Override
|
|
Prompt the user to restart because the computer has been up for a long time, overwriting any existing reminder schedule.
|
|
|
|
.EXAMPLE
|
|
Set-RebootSchedule -Remove
|
|
There is no longer a need to remind the user to restart, or you just want to clear an existing reminder schedule.
|
|
|
|
.NOTES
|
|
Calling this script with no parameters does nothing, the script will just exit without prompting the user for anything.
|
|
|
|
This is the order of schedule priority when this script is called:
|
|
1.) SysPerf
|
|
2.) OSUpdate
|
|
3.) Uptime
|
|
|
|
If -Uptime is called but a schedule has already been set by -OSUpdate, the user will not be prompted to schedule a restart.
|
|
If -OSUpdate is called but a schedule has already been set by -SysPerf, the user will not be prompted to schedule a restart.
|
|
If -SysPerf is called but a schedule has already been set by -OSUpdate, the user will be prompted to schedule a restart and the existing schedule will be overwritten.
|
|
|
|
The -Override parameter is used to modify this logic such that a lower priority schedule can overwrite a higher priority schedule.
|
|
|
|
#>
|
|
|
|
## Define parameters
|
|
Param(
|
|
[switch]$SysPerf,
|
|
[switch]$OSUpdate,
|
|
[switch]$Uptime,
|
|
[switch]$AllowMinimize=$false,
|
|
[switch]$Override,
|
|
[switch]$Force,
|
|
[switch]$Remove
|
|
)
|
|
|
|
## Add Windows Forms support to this script
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
[System.Windows.Forms.Application]::EnableVisualStyles()
|
|
|
|
## Functions and subroutines
|
|
#region begin FUNCTIONS {
|
|
|
|
## Copy this script to a directory where it can be called by a scheduled task
|
|
Function Copy-ThisScript {
|
|
|
|
## Get the current directory path and file name of this script
|
|
$ThisDirectory = Split-Path -Parent $MyInvocation.PSCommandPath
|
|
$ThisScript = Split-Path -Leaf $MyInvocation.PSCommandPath
|
|
|
|
## Check to make sure we don't copy this script if it's already been copied to $CopyDirectory
|
|
If ( !($ThisDirectory -eq $CopyDirectory) ) {
|
|
|
|
## Create the destination directory if it doesn't already exist
|
|
If ( !(Test-Path -Path $CopyDirectory) ) { New-Item -ItemType Directory -Force -Path $CopyDirectory }
|
|
|
|
## Delete the existing script in $CopyDirectory
|
|
If ( Test-Path -Path "${CopyDirectory}\${CopyFilename}" ) { Remove-Item -Path "${CopyDirectory}\${CopyFilename}" -Force }
|
|
|
|
## Copy the script to $CopyDirectory\$CopyFilename
|
|
Copy-Item -Path "${ThisDirectory}\${ThisScript}" -Destination "${CopyDirectory}\${CopyFilename}"
|
|
}
|
|
}
|
|
|
|
## Gets the number of days the system has been up.
|
|
Function Get-UptimeDays {
|
|
|
|
## Get a new instance of the Win32_OperatingSystem WMI object
|
|
$WMIOS = Get-WmiObject Win32_OperatingSystem
|
|
|
|
## Get the last boot time and convert it to a DateTime value
|
|
$LastBootTime = $WMIOS.ConvertToDateTime($WMIOS.LastBootUpTime)
|
|
|
|
## Get the number of days since the last time the system was powered on
|
|
[string]$Uptime = (New-TimeSpan -Start $LastBootTime -End $(Get-Date)).Days.ToString()
|
|
|
|
Return $Uptime
|
|
}
|
|
|
|
## Determines whether the logo can be downloaded or not
|
|
Function IsLogoDownloadable {
|
|
|
|
## Create a web request
|
|
$HTTPRequest = [System.Net.WebRequest]::Create($LogoURL)
|
|
|
|
## Get the response
|
|
Try { $HTTPResponse = $HTTPRequest.GetResponse() }
|
|
|
|
## Catch any error2 when trying to connect to the resource (including 404)
|
|
Catch [System.Net.WebException] { $HTTPResponse = $_.Exception.Response }
|
|
|
|
## Save the status code
|
|
$HTTPStatus = [int]$HTTPResponse.StatusCode
|
|
|
|
## Close the connection, because we're done with it
|
|
$HTTPResponse.Close()
|
|
|
|
## Test to make sure we received a status of 200 "OK" from the resource
|
|
If ($HTTPStatus -eq 200) { Return $true }
|
|
|
|
## If the status code is anything other than 200, return $false so we can do something else
|
|
Else { Return $false }
|
|
}
|
|
|
|
## Returns the local path of a file downloaded from a URL
|
|
Function Get-LogoPath {
|
|
|
|
## Get the file name from $url
|
|
$filename = [System.IO.Path]::GetFileName($LogoURL)
|
|
|
|
## Set the destination to download to
|
|
$localpath = "${Env:TEMP}\${filename}"
|
|
|
|
## Make sure the file is downloadable
|
|
If ( IsLogoDownloadable ) {
|
|
|
|
## Try downloading the file
|
|
Try { (New-Object Net.WebClient).DownloadFile($LogoURL, $localpath) }
|
|
|
|
## If you want to handle any download errors, put that code in here
|
|
Catch { $_ }
|
|
}
|
|
|
|
## Now that the file *may* be downloaded, check to make sure it exists
|
|
If ( Test-Path $localpath ) {
|
|
|
|
## Return $localpath to the caller
|
|
Return $localpath
|
|
}
|
|
|
|
## If $localpath doesn't exist (ie: from a previous execution of this script) then return $false
|
|
Else { Return $false }
|
|
}
|
|
|
|
## Base64 encode something
|
|
Function Get-Base64($data) {
|
|
$bytes = [System.Text.Encoding]::Unicode.GetBytes($data)
|
|
$encoded = [Convert]::ToBase64String($bytes)
|
|
Return $encoded
|
|
}
|
|
|
|
## Create a scheduled task
|
|
Function Create-ScheduledTask([string]$name,[string]$description,$action,$principal,$trigger) {
|
|
|
|
## Unregister any existing task with the same name as the one we're trying to create
|
|
## This needs to be fixed. If the task does not exist, it throws an error.
|
|
Try { Unregister-ScheduledTask -TaskName $name -Confirm:$false }
|
|
Catch { $_ }
|
|
|
|
## Configure the task
|
|
$Task = New-ScheduledTask -Description $description -Action $action -Principal $principal -Trigger $trigger
|
|
|
|
## Register the scheduled task
|
|
Register-ScheduledTask -TaskName $name -InputObject $Task
|
|
}
|
|
|
|
## Create a task to delete another task
|
|
## This will run at boot time to make sure that the user doesn't get unnessarily disrupted by
|
|
## a previously scheduled restart task after the computer has already been restarted.
|
|
Function Create-DeleteTask([string]$tasktodelete) {
|
|
|
|
## Create a RunOnce task to delete the specified task in the Task Scheduler
|
|
## PROBLEM: How can this occur if the user isn't an admin?
|
|
## Will this work the same if we write to HKCU instead?
|
|
#Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -Name '!DeleteScheduledRebootReminder' -Value "schtasks.exe /Delete /TN ${tasktodelete} /F"
|
|
|
|
## Set the task name
|
|
$TaskName = "${CompanyAbbr} - Delete Task: ${tasktodelete}"
|
|
|
|
## Se the task description
|
|
$TaskDescription = "This task deletes the task: ${tasktodelete}"
|
|
|
|
## Configure the task action
|
|
$args = "/delete /tn " + '"' + "\${tasktodelete}" + '"' + " /f"
|
|
$TaskAction = New-ScheduledTaskAction -Execute "schtasks.exe" -Argument $args
|
|
|
|
## Configure the user account the task will run under
|
|
$TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
|
|
## Configure the trigger to start at the specified time
|
|
$Trigger = New-ScheduledTaskTrigger -AtStartup
|
|
|
|
}
|
|
|
|
## Create a restart task
|
|
#Function Create-RestartTask([datetime]$starttime) {
|
|
#
|
|
# ## Set the task name
|
|
# $TaskName = "${CompanyAbbr} - Computer Restart Task"
|
|
#
|
|
# ## Set the task description
|
|
# $TaskDescription = "This task restarts the computer"
|
|
#
|
|
# ## Convert $script to Base64
|
|
# $EncodedScript = Get-Base64 $RestartComputerTaskScript
|
|
#
|
|
# ## Configure the task action
|
|
# $TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${EncodedScript}"
|
|
#
|
|
# ## Configure the user account the task will run under
|
|
# $TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
#
|
|
# ## Configure the trigger to start at the specific time
|
|
# $Trigger = New-ScheduledTaskTrigger -Once -At $starttime
|
|
#
|
|
# ## Create a new task to delete the one we're about to create the next time the compter boots
|
|
# Create-DeleteTask $TaskName
|
|
#
|
|
# ## Create the restart task
|
|
# Create-ScheduledTask $TaskName $TaskDescription $TaskAction $TaskPrincipal $TaskTrigger
|
|
#}
|
|
|
|
## Create a reminder task
|
|
#Function Create-ReminderTask([datetime]$starttime) {
|
|
#
|
|
# ## Set the task name
|
|
# $TaskName = "${CompanyAbbr} - Computer Restart Reminder Task"
|
|
#
|
|
# ## Set the task description
|
|
# $TaskDescription = "This task reminds the user to restart their computer"
|
|
#
|
|
# ## Convert $script to Base64
|
|
# $EncodedScript = Get-Base64 $ReminderTaskScript
|
|
#
|
|
# ## Configure the task action
|
|
# $TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${EncodedScript}"
|
|
#
|
|
# ## Configure the user account the task will run under
|
|
# $TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
#
|
|
# ## Configure the trigger to start at boot
|
|
# $Trigger = New-ScheduledTaskTrigger -Once -At $starttime
|
|
#
|
|
# ## Create the restart task
|
|
# Create-ScheduledTask $TaskName $TaskDescription $TaskAction $TaskPrincipal $TaskTrigger
|
|
#
|
|
# ## Create a new task to delete the one we just created the next time the compter boots
|
|
# Create-DeleteTask $TaskName
|
|
#}
|
|
|
|
## Create a reminder task
|
|
Function Create-ReminderTask([datetime]$starttime) {
|
|
|
|
## Set the task name
|
|
$TaskName = "${CompanyAbbr} - Computer Restart Reminder Task"
|
|
|
|
## Set the task description
|
|
$TaskDescription = "This task reminds the user to restart their computer"
|
|
|
|
## Convert $script to Base64
|
|
$EncodedScript = Get-Base64 $ReminderTaskScript
|
|
|
|
## Configure the task action
|
|
$TaskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -File `"${CopyDirectory}\${CopyFilename}`""
|
|
|
|
## Configure the user account the task will run under
|
|
$TaskPrincipal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
|
|
|
|
## Configure the trigger to start at boot
|
|
$Trigger = New-ScheduledTaskTrigger -Once -At $starttime
|
|
|
|
## Create the restart task
|
|
Create-ScheduledTask $TaskName $TaskDescription $TaskAction $TaskPrincipal $TaskTrigger
|
|
|
|
## Create a new task to delete the one we just created the next time the compter boots
|
|
Create-DeleteTask $TaskName
|
|
}
|
|
|
|
## Determine if the current time is earlier than the given time
|
|
#Function EarlierThan($time) {
|
|
#
|
|
# ## If it's earlier, return $true
|
|
# If ( (Get-Date) -lt $time ) { Return $true }
|
|
#
|
|
# ## If it's later, return false
|
|
# Else { Return $false }
|
|
#}
|
|
|
|
## Get the closest time to schedule a restart
|
|
#Function Get-NearestRestartTime {
|
|
#
|
|
# ## Find out what day it is
|
|
# switch ( (Get-Date).DayOfWeek ) {
|
|
#
|
|
# ## On weekends, the nearest time to schedule a restart will be:
|
|
# ## 1.) Lunch time
|
|
# ## 2.) Sometime in the afternoon
|
|
# ## 3.) About 20 minutes from the current time
|
|
# { $WeekendDays -contains $_ } {
|
|
#
|
|
# ## If it's earlier than $Lunchime, return $LunchTime
|
|
# If ( EarlierThan $LunchTime ) { Return $LunchTime }
|
|
#
|
|
# ## If it's earlier than $AfternoonTime, return $AfternoonTime
|
|
# ElseIf ( EarlierThan $AfternoonTime ) { Return $AfternoonTime }
|
|
#
|
|
# ## If it's after $AfternoonTime, return $ShortTimeFromNow
|
|
# Else { Return $ShortTimeFromNow }
|
|
# break
|
|
# }
|
|
# ## Throughout the week the nearest time to remind to restart will be:
|
|
# ## 1.) Lunch time
|
|
# ## 2.) Close of business
|
|
# ## 3.) Late at night
|
|
# { $WeekDays -contains $_ } {
|
|
#
|
|
# ## If it's earlier than $LunchTime, return $LunchTime
|
|
# If ( EarlierThan $LunchTime ) { Return $LunchTime }
|
|
#
|
|
# ## If it's earlier than $CloseOfBusiness, return $CloseOfBusiness
|
|
# ElseIf ( EarlierThan $CloseOfBusiness ) { Return $CloseOfBusiness }
|
|
#
|
|
# ## If it's after $CloseOfBusiness, return $LateAtNight
|
|
# Else { Return $LateAtNight }
|
|
# break
|
|
# }
|
|
# default { break }
|
|
# }
|
|
#}
|
|
|
|
## Get the next time to remind the user to restart
|
|
#Function Get-NextReminderTime {
|
|
#
|
|
# ## Find out what day it is
|
|
# switch ( (Get-Date).DayOfWeek ) {
|
|
#
|
|
# { $TwoDayReminderDays -contains $_ } {
|
|
#
|
|
# ## Add 2 days to the current day, then add the $ReminderDelay
|
|
# $next = $StartOfBusiness + (New-TimeSpan -Days 2) + $ReminderDelay
|
|
# Return $next
|
|
# break
|
|
# }
|
|
#
|
|
# { $OneDayReminderDays -contains $_ } {
|
|
#
|
|
# ## Add 1 day to the current day, then add the $ReminderDelay
|
|
# $next = $StartOfBusiness + (New-TimeSpan -Days 1) + $ReminderDelay
|
|
# Return $next
|
|
# break
|
|
# }
|
|
# default { break }
|
|
# }
|
|
#}
|
|
|
|
Function Get-NextReminderTime {
|
|
|
|
$next = (Get-Date) + $ReminderInterval
|
|
Return $next
|
|
|
|
}
|
|
|
|
## Builds the Windows form to display to the user
|
|
Function Display-Prompt([string]$message) {
|
|
|
|
## Set the form's overall parameters
|
|
$Form = New-Object System.Windows.Forms.Form
|
|
$Form.ClientSize = '400,360'
|
|
$Form.Text = $WindowTitle
|
|
$Form.TopMost = $true
|
|
$Form.MaximizeBox = $false
|
|
$Form.MinimizeBox = $AllowMinimize
|
|
$Form.FormBorderStyle = 'FixedDialog'
|
|
$Form.StartPosition = 'CenterScreen'
|
|
|
|
## Download the logo
|
|
$Logo = (Get-LogoPath)
|
|
|
|
## Add a picturebox to the form
|
|
If ( $Logo ) {
|
|
$pbLogo = New-Object system.Windows.Forms.PictureBox
|
|
$pbLogo.Width = $Form.ClientSize.Width - 20
|
|
$pbLogo.Height = 90
|
|
$pbLogo.Anchor = [System.Windows.Forms.AnchorStyles]::None
|
|
$pbLogo.Location = New-Object System.Drawing.Point(10,10)
|
|
$pbLogo.ImageLocation = $Logo
|
|
$pbLogo.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::CenterImage
|
|
$Form.Controls.Add($pbLogo)
|
|
}
|
|
|
|
## If the logo isn't available, add label to the form instead of a picturebox
|
|
Else {
|
|
$lblCompany = New-Object System.Windows.Forms.Label
|
|
$lblCompany.Text = $CompanyName
|
|
$lblCompany.AutoSize = $false
|
|
## The TextAlign enumerations can be found here:
|
|
## https://docs.microsoft.com/en-us/dotnet/api/system.drawing.contentalignment?view=netframework-2.0
|
|
$lblCompany.TextAlign = 32
|
|
$lblCompany.Width = $Form.ClientSize.Width - 20
|
|
$lblCompany.Height = 60
|
|
$lblCompany.Location = New-Object System.Drawing.Point(10,10)
|
|
$lblCompany.Font = 'Microsoft Sans Serif,24,style=Bold'
|
|
$Form.Controls.Add($lblCompany)
|
|
}
|
|
|
|
## This is the label that contains the reason for the restart
|
|
$lblReason = New-Object System.Windows.Forms.Label
|
|
$lblReason.Text = $message
|
|
$lblReason.AutoSize = $false
|
|
$lblReason.TextAlign = 1
|
|
$lblReason.Width = $Form.ClientSize.Width - 50
|
|
$lblReason.Height = 180
|
|
$lblReason.Location = New-Object System.Drawing.Point(25,100)
|
|
$lblReason.Font = 'Microsoft Sans Serif,11'
|
|
$Form.Controls.Add($lblReason)
|
|
|
|
## This is the label that contains a static message about how to proceed
|
|
$lblProceed = New-Object System.Windows.Forms.Label
|
|
$lblProceed.Text = $ProceedText
|
|
$lblProceed.AutoSize = $true
|
|
$lblProceed.TextAlign = 1
|
|
$lblProceed.Location = New-Object System.Drawing.Point(25,280)
|
|
$lblProceed.Font = 'Microsoft Sans Serif,11'
|
|
$Form.Controls.Add($lblProceed)
|
|
|
|
# ## This is the button that displays the nearest time to schedule a reboot
|
|
# $btnNearestTime = New-Object System.Windows.Forms.Button
|
|
# $btnNearestTime.Text = (Get-Date -Date $NearestRestartTime -Format "hh:mm tt").ToString()
|
|
# $btnNearestTime.Width = 130
|
|
# $btnNearestTime.Height = 30
|
|
# $btnNearestTime.Location = New-Object System.Drawing.Point(45,310)
|
|
# $btnNearestTime.Font = 'Microsoft Sans Serif,11'
|
|
# $btnNearestTime.Add_Click({
|
|
#
|
|
# ## Create the "Computer Restart Task" scheduled task
|
|
# Create-ReminderTask $NearestRestartTime
|
|
#
|
|
# ## We're done for now, just close the window.
|
|
# $Form.Close()
|
|
# })
|
|
|
|
## This is the button that displays the nearest time to schedule a reboot
|
|
$btnNearestTime = New-Object System.Windows.Forms.Button
|
|
$btnNearestTime.Text = $RebootNowText
|
|
$btnNearestTime.Width = 130
|
|
$btnNearestTime.Height = 30
|
|
$btnNearestTime.Location = New-Object System.Drawing.Point(45,310)
|
|
$btnNearestTime.Font = 'Microsoft Sans Serif,11'
|
|
$btnNearestTime.Add_Click({
|
|
|
|
## Create the "Computer Restart Task" scheduled task
|
|
Restart-Computer
|
|
|
|
## We're done for now, just close the window.
|
|
$Form.Close()
|
|
})
|
|
|
|
$Form.AcceptButton = $btmNearestTime
|
|
$Form.Controls.Add($btnNearestTime)
|
|
|
|
## This is the placebo button, it just closes the form when clicked.
|
|
## The reminder schedule has already been created, so this button doesn't need to do anything.
|
|
$btnPlacebo = New-Object System.Windows.Forms.Button
|
|
$btnPlacebo.Text = $PlaceboText
|
|
$btnPlacebo.Width = 130
|
|
$btnPlacebo.Height = 30
|
|
$btnPlacebo.Location = New-Object System.Drawing.Point(225,310)
|
|
$btnPlacebo.Font = 'Microsoft Sans Serif,11'
|
|
$btnPlacebo.Add_Click({ $Form.Close() })
|
|
$Form.Controls.Add($btnPlacebo)
|
|
|
|
|
|
[void]$Form.ShowDialog()
|
|
}
|
|
|
|
#endregion FUNCTIONS }
|
|
|
|
#region begin SCRIPTS {
|
|
|
|
## This script is used to remind the user to restart their computer
|
|
$ReminderTaskScript = '&{
|
|
## code here
|
|
}'
|
|
|
|
#endregion SCRIPTS }
|
|
|
|
## Define custom company name, logo, window title, and messages
|
|
#region begin CUSTOMIZATIONS {
|
|
|
|
## The following 2 settings are specific to your company
|
|
## This is the name of your company.
|
|
$CompanyName = "Emberkom"
|
|
## This is the short or abbreviated name of your company
|
|
## It's used to prefix the scheduled tasks so they're easy to identify
|
|
$CompanyAbbr = "EK"
|
|
## This is the URL to your company logo.
|
|
## If your company logo cannot be downloaded, $CompanyName will be used instead.
|
|
## If the image you specify is larger than 380x90, it will shrink to fit that size.
|
|
$LogoURL = 'https://emberkom.s3.amazonaws.com/management/scripts/resources/small-web-logo.jpg'
|
|
|
|
## This script will start by copying itself into a local directory on the computer.
|
|
## This will allow the scheduled tasks this script creates to call it later.
|
|
## Directory to copy this script into (do not put in an ending "\")
|
|
$CopyDirectory = "${Env:ProgramData}\${CompanyName}\Scripts"
|
|
## The name of the file this script should have when copied to the $CopyDirectory
|
|
$CopyFilename = "Set-RebootSchedule.ps1"
|
|
|
|
## The following 6 settings control text displayed on the form when prompting the user to choose a time to restart their computer
|
|
## The title of the window
|
|
$WindowTitle = "Restart Required - ${CompanyName}"
|
|
## The message displayed to the user when -SysPerf is called.
|
|
$SysPerfText = "It looks like your computer isn't performing like it should.`n`nRestarting it will help to resolve some of the problems its been having."
|
|
## The message displayed to the user when -OSUpdate is called.
|
|
$OSUpdateText = "Good news!`n`nYour computer has recently installed some updates and it needs to be restarted soon."
|
|
## Thhe message displayed to the user when -Uptime is called.
|
|
$UptimeText = "It looks like your computer has been on for more than $(Get-UptimeDays) days.`n`nIt's probably best to restart soon so it doesn't start causing problems for you."
|
|
## This is the message displayed just above the buttons - it should ask the user how they want to proceed
|
|
$ProceedText = "When can we make this happen?"
|
|
## This is the text for a placebo button. Regardless of whether the user clicks this button or not,
|
|
## a reminder has already been created. Clicking the button will just close the form.
|
|
## This is simply because I don't want the user to be able to dismiss restarting their
|
|
## computer, but I still want them to feel like they're involved and have some control
|
|
## over the situation. Automatically reminding them some other time won't hurt anything.
|
|
$PlaceboText = "Remind me later"
|
|
|
|
|
|
############### NEW SETTINGS ###############
|
|
|
|
## The message on the button that immediately restarts the computer
|
|
$RebootNowText = "Restart Now"
|
|
|
|
## When to begin notifying the user they need to reboot their computer
|
|
$StartReminderAt = Get-Date -Hour 9 -Minute 0 -Second 0
|
|
|
|
## When to stop notifying the user to reboot.
|
|
## If the next notification to restart is scheduled to happen after this time,
|
|
## it will be automatically rescheduled until $StartReminderAt of the following day.
|
|
$StopReminderAt = Get-Date -Hour 16 -Minute 50 -Second 0
|
|
|
|
## The amount of time between restart notifications
|
|
$ReminderInterval = New-TimeSpan -Hours 2 -Minutes 45
|
|
|
|
|
|
## This is some small amount of time in the future where the user can schedule a reboot. This isn't used often, but is used
|
|
## The formula used here will add 20 minutes to the current time and round it to the nearest 5 minute mark.
|
|
## I referenced the code by Tony Hinkle in this post:
|
|
## https://stackoverflow.com/questions/39728485/rounding-down-minutes-to-the-nearest-10-minutes#39728699
|
|
$ShortTimeFromNow = (Get-Date).AddMinutes(-(((Get-Date).Minute % 5) - 20))
|
|
|
|
## The following 5 settings configure the date and time this script will use to schedule reminders and restarts
|
|
## All times will be today's date at the hour, minute, and second specified.
|
|
## Specify the business start time.
|
|
## This time is used to remind the user to restart their computer. The reminder won't show up until at least the value defined here.
|
|
## The $ReminderDelay time will be added to $StartOfBusiness to come up with the time to remind the user to restart their computer.
|
|
$StartOfBusiness = Get-Date -Hour 8 -Minute 30 -Second 0
|
|
## Specify the lunch time
|
|
## This time is used to schedule a restart all through the week and weekends.
|
|
$LunchTime = Get-Date -Hour 12 -Minute 0 -Second 0
|
|
## Specify the afternoon time
|
|
## This time is used to schedule a restart only on the weekends and is based on $LunchTime
|
|
$AfternoonTime = $LunchTime + (New-TimeSpan -Hours 2 -Minutes 30)
|
|
## Specify the close-of-business time. In reality this should be a little bit before the actual close of business time.
|
|
## This time is used to remind to restart only during the weekdays. This should be just before everyone starts leaving the office.
|
|
$CloseOfBusiness = Get-Date -Hour 16 -Minute 50 -Second 0
|
|
## Specify the late-at-night time
|
|
## This time is used to schedule a restart only during the weekdays. You should use a time when users are least likely to work
|
|
$LateAtNight = Get-Date -Hour 22 -Minute 0 -Second 0
|
|
|
|
## Specify delay after the $StartOfBusiness when the user will be reminded to restart
|
|
## If the user does not restart, this is used to delay the reminder until most people are in the office
|
|
## For example: if $StartOfBusiness is 8am, but most people aren't in the office until 8:30am,
|
|
## you'll want to specify a value of 30 minutes here.
|
|
## They probably don't want to come in and immediately see a reminder to restart their computer. Let them get coffee first :-)
|
|
$ReminderDelay = New-TimeSpan -Minutes 40
|
|
|
|
## The next two settings define the week for your customer.
|
|
## If their weekend is not Saturday and Sunday, define that here.
|
|
## Weekend days
|
|
$WeekendDays = @("Saturday","Sunday")
|
|
## Week days
|
|
$WeekDays = @("Monday","Tuesday","Wednesday","Thursday","Friday")
|
|
|
|
## The next two settings define the 2-day reminders and the 1-day reminders.
|
|
## On the day this script is run, a reminder is automatically created.
|
|
## If the user closes the window or clicks the placebo button, the reminder is already created
|
|
## for either the next day, or 2 days from now.
|
|
## If you changed the previous 2 settings to specify different weekend and week days,
|
|
## you'll probably want to change this setting too.
|
|
## The idea behind this is to guide the user to restarting their computer sooner rather than later.
|
|
## The default options will push them towards restarting at the end of the work week, but if the
|
|
## script runs on the weekend, the reminder won't bother them again until the start of the work week.
|
|
## Specify the 2-day reminder days (user will be reminded 2 days after the days in this setting)
|
|
$TwoDayReminderDays = @("Monday","Tuesday","Wednesday","Saturday")
|
|
## Specify the 1-day reminder days (user will be reminded the day after the days in this setting)
|
|
$OneDayReminderDays = @("Thursday","Friday","Sunday")
|
|
|
|
#endregion CUSTOMIZATIONS }
|
|
|
|
## This is where we do everything needed to either prompt or remind the user to restart their computer
|
|
## This will involve copying the script locally, checking for existing reminder priorities, etc...
|
|
#region begin PREFLIGHT {
|
|
|
|
## Copy this script to $CopyDirectory if it isn't being run from $CopyDirectory
|
|
If ( $MyInvocation.PSCommandPath -ne "${CopyDirectory}\${CopyFilename}" ) { Copy-ThisScript }
|
|
|
|
## Disallow this script to display to the user before we check the parameters
|
|
$AllowDisplay = $false
|
|
|
|
## If the last argument is -Task, then make sure we allow this script to display to the user
|
|
If ( $args[$args.Count - 1].ToString() -ieq "-Task" ) { $AllowDisplay = $true }
|
|
|
|
## If the last argument isn't -Task, then we need to create a scheduled task for 10 seconds from now to run this script
|
|
Else {
|
|
|
|
Write-Host "No Task"
|
|
}
|
|
|
|
|
|
#endregion PREFLIGHT }
|
|
|
|
## This is where we gather the necessary info and prompt the user to restart
|
|
#region begin DISPLAY_FORM
|
|
|
|
## Get the nearest time to schedule a restart
|
|
#$NearestRestartTime = Get-NearestRestartTime
|
|
|
|
## Get the next reminder time
|
|
$NextReminderTime = Get-NextReminderTime
|
|
|
|
##
|
|
|
|
## Display the form
|
|
If ( $AllowDisplay ) { Display-Prompt $SysPerfText }
|
|
|
|
#endregion DISPLAY_FORM
|