Inital commit.
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
<#
|
||||
|
||||
.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.
|
||||
|
||||
.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 prompt be minimized by the user.
|
||||
By default, the user is not allowed to minimize the window.
|
||||
|
||||
.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.
|
||||
|
||||
.NOTES
|
||||
Calling this script with no parameters does nothing, the script will just exit without prompting the user for anything.
|
||||
#>
|
||||
|
||||
## Define parameters
|
||||
|
||||
Param(
|
||||
[switch]$SysPerf=$false,
|
||||
[switch]$OSUpdate=$false,
|
||||
[switch]$Uptime=$false,
|
||||
[switch]$AllowMinimize=$false
|
||||
)
|
||||
|
||||
## Get the name of this script
|
||||
$ScriptName = $MyInvocation.MyCommand.Name
|
||||
|
||||
## Get a list of running PowerShell scripts
|
||||
$RUnningPSScripts = Get-WmiObject Win32_Process -Filter "Name='powershell.exe'" | Select-Object ProcessId,CommandLine
|
||||
|
||||
## Loop through all other running instances of this script and kill each one that isn't the current instance.
|
||||
ForEach ( $script in $RUnningPSScripts ) {
|
||||
$OtherPID = $script.ProcessId
|
||||
$OtherCMD = $script.CommandLine
|
||||
|
||||
## Check for other instances of this script that might be running
|
||||
If ( ($OtherCMD -like "*${ScriptName}*") -and ($OtherPID -ne $PID) ) {
|
||||
|
||||
## Kill the other instance
|
||||
Stop-Process -Id $script.ProcessId -Force
|
||||
}
|
||||
}
|
||||
|
||||
## Add Windows Forms support to this script
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
||||
|
||||
## Functions and subroutines
|
||||
#region begin FUNCTIONS {
|
||||
|
||||
## 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 }
|
||||
}
|
||||
|
||||
|
||||
## 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
|
||||
$btnRestartNow = New-Object System.Windows.Forms.Button
|
||||
$btnRestartNow.Text = $RestartNowText
|
||||
$btnRestartNow.Width = 130
|
||||
$btnRestartNow.Height = 30
|
||||
$btnRestartNow.Location = New-Object System.Drawing.Point(45,310)
|
||||
$btnRestartNow.Font = 'Microsoft Sans Serif,11'
|
||||
$btnRestartNow.Add_Click({
|
||||
|
||||
## Restart the computer
|
||||
Restart-Computer
|
||||
|
||||
## We're done for now, just close the window.
|
||||
$Form.Close()
|
||||
})
|
||||
|
||||
$Form.AcceptButton = $btmRestartNow
|
||||
$Form.Controls.Add($btnRestartNow)
|
||||
|
||||
## 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.
|
||||
$btnCancel = New-Object System.Windows.Forms.Button
|
||||
$btnCancel.Text = $CancelText
|
||||
$btnCancel.Width = 130
|
||||
$btnCancel.Height = 30
|
||||
$btnCancel.Location = New-Object System.Drawing.Point(225,310)
|
||||
$btnCancel.Font = 'Microsoft Sans Serif,11'
|
||||
$btnCancel.Add_Click({ $Form.Close() })
|
||||
$Form.Controls.Add($btnCancel)
|
||||
|
||||
|
||||
[void]$Form.ShowDialog()
|
||||
}
|
||||
|
||||
#endregion FUNCTIONS }
|
||||
|
||||
## 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 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 be centered in that area (clipping will occur).
|
||||
$LogoURL = 'https://emberkom.s3.amazonaws.com/management/scripts/resources/small-web-logo.png'
|
||||
|
||||
## The following 7 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."
|
||||
## The 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 = "Can we make this happen?"
|
||||
## This is the text for the cancel button. Clicking this button will just close the form
|
||||
$CancelText = "Remind me later"
|
||||
## The message on the button that immediately restarts the computer
|
||||
$RestartNowText = "Restart Now"
|
||||
|
||||
#endregion CUSTOMIZATIONS }
|
||||
|
||||
## Display the form
|
||||
If ( $SysPerf ) { Display-Prompt $SysPerfText }
|
||||
ElseIf ( $OSUpdate ) { Display-Prompt $OSUpdateText }
|
||||
ElseIF ( $Uptime ) { Display-Prompt $UptimeText }
|
||||
Reference in New Issue
Block a user