esPreSso.psm1
#Region '.\Private\ConvertKey-ToSendKeys.ps1' -1 function ConvertKey-ToSendKeys { <# .SYNOPSIS Converts a chosen key to appropriate format for use with the WScript SendKeys method .DESCRIPTION Most keys from the keyboard can simply be passed to SendKeys but some require special formatting. This function is meant to handle the special circumstances .PARAMETER Key the key to convert #> [CmdletBinding()] param ( [String]$Key ) $SpecialKeys = @{ ')' = '{)}' '(' = '{(}' '~' = '{~}' '^' = '{^}' '+' = '{+}' '%' = '{%}' Shift = '+' Backspace = '{Backspace}' Break = '{Break}' CapsLock = '{CapsLock}' Delete = '{Delete}' Down = '{Down}' End = '{End}' Enter = '{Enter}' Esc = '{Esc}' Help = '{Help}' Home = '{Home}' Insert = '{Insert}' Left = '{Left}' Numlock = '{Numlock}' PageDown = '{PGDN}' PageUp = '{PGUP}' PrintScreen = '{PRTSC}' Right = '{Right}' ScrollLock = '{ScrollLock}' Tab = '{Tab}' Up = '{Up}' F1 = '{F1}' F2 = '{F2}' F3 = '{F3}' F4 = '{F4}' F5 = '{F5}' F6 = '{F6}' F7 = '{F7}' F8 = '{F8}' F9 = '{F9}' F10 = '{F10}' F11 = '{F11}' F12 = '{F12}' F13 = '{F13}' F14 = '{F14}' F15 = '{F15}' F16 = '{F16}' } if ($SpecialKeys[$Key]) { $SpecialKeys[$Key] } else { $Key } } #EndRegion '.\Private\ConvertKey-ToSendKeys.ps1' 68 #Region '.\Public\Get-KeepAwake.ps1' -1 function Get-KeepAwake { <# .SYNOPSIS Checks the registered scheduled tasks for the esPreSso job that runs Start-KeepAwake .DESCRIPTION Checks the registered scheduled tasks for the esPreSso job that runs Start-KeepAwake and return an object representing its settings .EXAMPLE PS> Get-KeepAwake TaskPath TaskName State -------- -------- ----- \Microsoft\Windows\PowerShell\ScheduledJobs\ esPreSso Ready #> [CmdletBinding()] param () $TaskName = "esPreSso" $TaskPath = "\Microsoft\Windows\PowerShell\ScheduledJobs\" try { Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -ErrorAction Stop } catch { Write-Verbose "esPreSso scheduled task not found" } } #EndRegion '.\Public\Get-KeepAwake.ps1' 26 #Region '.\Public\Get-Keys.ps1' -1 function Get-Keys { <# .SYNOPSIS Return an array of keys that be specified with the -Key parameter of Start-KeepAwake .DESCRIPTION Returns an array of possible keys that can be used with the -Key parameter of Start-KeepAwake .EXAMPLE PS> Get-Keys ! " # $ % & ' ( ) * + ... truncated example output as this will print 131 possible keys. This public function is mostly used in conjunction with Start-KeepAwake to support auto completion with the -Key parameter #> [Cmdletbinding()] param () $Keys = [System.Collections.ArrayList]::new() 33..126 | Foreach-Object { [Void]$Keys.Add([char]$_) } $SpecialKeys = @( "Shift", "Backspace", "Break", "CapsLock", "Delete", "Down", "End", "Enter", "Esc", "Help", "Home", "Insert", "Left", "Numlock", "PageDown", "PageUp", "PrintScreen", "Right", "ScrollLock", "Tab", "Up", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16" ) $SpecialKeys | Foreach-Object { [Void]$Keys.Add($_) } return $Keys } #EndRegion '.\Public\Get-Keys.ps1' 75 #Region '.\Public\Register-KeepAwake.ps1' -1 function Register-KeepAwake { <# .SYNOPSIS registers a scheduled job to run Start-KeepAwake at user login .DESCRIPTION registers a scheduled job to run Start-KeepAwake at user login. Allows control over the Start-KeepAwake settings as well as some scheduled job settings. .EXAMPLE PS> Register-KeepAwake when ran in an administrative PowerShell session this will create a scheduled task that runs at logon and starts Start-KeepAwake with the -PowerControl parameter #> [CmdletBinding()] param () # check if we're running as admin and quit if not $IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) if ($IsAdmin) { # get the currently logged in user in case the PowerShell session was elevated via a different username than the one logged in to the computer $UserName = (Get-CimInstance -Class Win32_ComputerSystem).Username $ActionArgs = 'powershell.exe -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -Command "& {Start-KeepAwake -PowerControl}"' $TaskSettings = @{ Action = $(New-ScheduledTaskAction -Execute "Conhost.exe" -Argument $ActionArgs) Principal = $(New-ScheduledTaskPrincipal -UserId $Username -LogonType Interactive) TaskName = "esPreSso" TaskPath = "\Microsoft\Windows\PowerShell\ScheduledJobs\" Trigger = $(New-ScheduledTaskTrigger -AtLogOn -User $UserName) } $ExistingTask = Get-KeepAwake if ($ExistingTask) { Remove-KeepAwake } Register-ScheduledTask @TaskSettings } else { Write-Warning "Registering a scheduled task requires elevation. Please re-run PowerShell with 'run as administrator' and try again." } } #EndRegion '.\Public\Register-KeepAwake.ps1' 38 #Region '.\Public\Remove-KeepAwake.ps1' -1 function Remove-KeepAwake { <# .SYNOPSIS Removes the esPreSso scheduled task from Task Scheduler .DESCRIPTION Unregisters the scheduled task created by Register-KeepAwake. There is no output. .EXAMPLE PS> Remove-KeepAwake if there is an existing scheduled task for esPreSso this will cleanly remove it from Task Scheduler. #> [CmdletBinding()] param () $ScheduledTask = Get-KeepAwake if ($ScheduledTask) { $IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) if ($IsAdmin) { Write-Verbose "Removing scheduled task named $($ScheduledTask.TaskName) in $($ScheduledTask.TaskPath)" Unregister-ScheduledTask -InputObject $ScheduledTask -Confirm:$false } else { Write-Warning "Removing a scheduled task requires elevation. Please re-run PowerShell and 'run as administrator' and try again." } } else { Write-Warning "No scheduled task for esPreSso found" } } #EndRegion '.\Public\Remove-KeepAwake.ps1' 28 #Region '.\Public\Start-KeepAwake.ps1' -1 function Start-KeepAwake { <# .SYNOPSIS This function attempts to keep the computer awake by sending a key-press every 60 seconds (by default) .DESCRIPTION Using the WScript namespace to send keys this function will send a key combination of F15 every 60 seconds by default to keep the computer awake and preven the screensaver from activating. .PARAMETER Minutes Number of minutes to run the keep awake .PARAMETER Hours Number of hours to run the keep awake .PARAMETER Until A date time representing when to stop running the keep awake. Accepts common datetime formats .PARAMETER Interval The interval for how often a key press is sent. Default is 60 seconds and this should be fine for most scenarios. .PARAMETER Key Optionally can specify which keypress to send. The default, and most widely tested is F15, but just about any key on the keyboard can be specified. Supports tab completion to see which keys can be selected .PARAMETER PowerControl Switch parameter that tells Start-KeepAwake to register a request via SetThreadExecutionState to keep the display awake and prevent sleep. Cancelled with Ctrl+C or other terminating signal. .EXAMPLE PS> Start-KeepAwake When ran with no parameters the function will attempt to keep the computer awake indefinitely until cancelled. .EXAMPLE PS> Start-KeepAwake -Until "3:00pm" will send a keypress of F15 every minute until 3:00 pm the same day .EXAMPLE PS> Start-KeepAwake -Key Shift -Interval 10 will send a press of the 'shift' key every 10 seconds .EXAMPLE PS> Start-KeepAwake -PowerControl Will also attempt to keep the computer awake indefinitely but won't send any key presses. .NOTES Credit to marioraulperez for his class definition: https://github.com/marioraulperez/keep-windows-awake #> [CmdletBinding(DefaultParameterSetName = 'Manual')] [Alias("nosleep","ka")] Param( [Parameter(Position=1, ParameterSetName='Manual')] [Alias("m")] [Int32]$Minutes, [Parameter(Position=0, ParameterSetName='Manual')] [Alias("h")] [Int32]$Hours, [Parameter(ParameterSetName='Until')] [Alias("u")] [DateTime]$Until, [Parameter(ParameterSetName='Manual')] [Parameter(ParameterSetName='Until')] [ValidateRange(1,86400)] [Int32]$Interval = 60, [Parameter(ParameterSetName='Manual')] [Parameter(ParameterSetName='Until')] [ArgumentCompleter({ param ($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) $ValidValues = Get-Keys $ValidValues -like "$WordToComplete*" })] [ValidateScript({ if ($_ -in (Get-Keys)) { $true } else { throw "$_ is not a valid key option" } })] [String]$Key = 'F15', [Parameter(ParameterSetName='PowerPlan')] [Switch]$PowerControl ) if ($PowerControl) { try { $Definition = @" using System; using System.Runtime.InteropServices; public class PowerCtrl { [DllImport("kernel32.dll", SetLastError = true)] public static extern uint SetThreadExecutionState(uint esFlags); public static void PreventSleep() { // ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED SetThreadExecutionState(0x80000002 | 0x00000001 | 0x00000002); } public static void AllowSleep() { // ES_CONTINUOUS SetThreadExecutionState(0x80000000); } } "@ Add-Type -Language CSharp -TypeDefinition $Definition Write-Verbose "Preventing sleep via PowerCtrl" $BackgroundJob = Start-Job -Name "esPreSso" -ScriptBlock { Add-Type -Language CSharp -TypeDefinition $args[0] [PowerCtrl]::PreventSleep() while ($true) { Start-Sleep -Seconds 60 } } -ArgumentList $Definition Wait-Job -Job $BackgroundJob } catch { Write-Error $_ } finally { Write-Verbose "Removing PowerCtrl" Stop-Job -Job $BackgroundJob Remove-Job -Job $BackgroundJob [PowerCtrl]::AllowSleep() } } else { $TSParams = @{} switch ($PSBoundParameters.Keys) { 'Minutes' { $TSParams.Add('Minutes', $Minutes) Write-Verbose "Adding $Minutes minutes of duration" } 'Hours' { $TSParams.Add('Hours', $Hours) Write-Verbose "Adding $Hours hours of duration" } 'Until' { Write-Verbose "Stopping time provided of: $($Until.ToShortTimeString())" $UntilDuration = ($Until - (Get-Date)).TotalMinutes If ($UntilDuration -lt 1) { $UntilDuration = 1 } Write-Verbose "Adding $UntilDuration minutes of duration" $TSParams.Add('Minutes', $UntilDuration) } } if (-not $TSParams.Count) { Write-Verbose "Defaulting to indefinite runtime" $Duration = $true } else { $Duration = (New-TimeSpan @TSParams).TotalMinutes Write-Verbose "Total duration is $Duration minutes" } $WShell = New-Object -ComObject WScript.Shell Write-Verbose $('Keeping computer awake by sending "{0}" every {1} seconds' -f $Key, $Interval) $SendKeyValue = ConvertKey-ToSendKeys -Key $Key while ($RunTime -le $Duration) { if ($Duration.GetType().Name -ne "Boolean") { Write-Verbose $('{0:n2} minutes remaining' -f ($Duration - $Runtime)) $Runtime += $($Interval/60) } $WShell.SendKeys($SendKeyValue) Start-Sleep -seconds $Interval } } } #EndRegion '.\Public\Start-KeepAwake.ps1' 157 |