Skip to content

Instantly share code, notes, and snippets.

@TheFreeman193
Created March 8, 2021 15:34
Show Gist options
  • Save TheFreeman193/dfc543524187573bf4116ec2dab810a7 to your computer and use it in GitHub Desktop.
Save TheFreeman193/dfc543524187573bf4116ec2dab810a7 to your computer and use it in GitHub Desktop.
Proof of concept for brute-force interaction with Alarms & Clock
<#
.SYNOPSIS
Proof of Concept. Starts a new Alarms & Clock (Time.exe) timer in Windows 10.
.DESCRIPTION
Proof of Concept. Starts a new Alarms & Clock (Time.exe) timer in Windows 10.
It does this by emulating keystroke input. DO NOT USE THIS IN PRODUCTION
ENVIRONMENTS.
.PARAMETER Time
The complete time for the timer. This must be a valid System.TimeSpan.
.PARAMETER Hours
The number of hours for the timer. Valid values are 0-99.
.PARAMETER Minutes
The number of hours for the timer. Valid values are 0-59.
.PARAMETER Seconds
The number of hours for the timer. Valid values are 0-59.
.PARAMETER Name
The name or label for the timer.
.INPUTS
None. Start-MSTimer does not accept pipeline input.
.OUTPUTS
None. Start-MSTimer does not produce any output.
.EXAMPLE
PS> .\Start-MSTimer.ps1 -Time '00:30:00' -Name 'My 30 minute timer'
Starts a new 30 minute timer.
.EXAMPLE
PS> .\Start-MSTimer.ps1 -Hours 1 -Minutes 30 -Name 'My 1:30 timer'
Starts a new 1 hour 30 minute timer using explicit parameters.
.EXAMPLE
PS> .\Start-MSTimer.ps1 -Seconds 300
Starts a new 5 minute timer with the default name, using the seconds parameter.
.NOTES
DO NOT USE THIS IN PRODUCTION ENVIRONMENTS, THIS IS A PROOF OF CONCEPT.
.LINK
https://gist.github.com/TheFreeman193/dfc543524187573bf4116ec2dab810a7
#>
[CmdletBinding(DefaultParameterSetName = 'S', PositionalBinding = $false)]
param (
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'TimeSpan')]
[Alias('T')]
[timespan]
$Time,
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'S')]
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'MS')]
[Parameter(Mandatory = $true, Position = 2, ParameterSetName = 'HMS')]
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'HS')]
[ValidateRange(0, 59)]
[Alias('H')]
[UInt16]
$Seconds,
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'M')]
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'HMS')]
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'MS')]
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = 'HM')]
[ValidateRange(0, 59)]
[Alias('M')]
[UInt16]
$Minutes,
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'H')]
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'HMS')]
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'HM')]
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'HS')]
[ValidateRange(0, 99)]
[Alias('S')]
[UInt16]
$Hours,
[Parameter(Position = 1, ParameterSetName = 'H')]
[Parameter(Position = 1, ParameterSetName = 'M')]
[Parameter(Position = 1, ParameterSetName = 'S')]
[Parameter(Position = 3, ParameterSetName = 'HMS')]
[Parameter(Position = 2, ParameterSetName = 'HM')]
[Parameter(Position = 2, ParameterSetName = 'HS')]
[Parameter(Position = 1, ParameterSetName = 'TimeSpan')]
[ValidatePattern('^[\x20-\x7E]+$')]
[Alias('Label')]
[string]
$Name
)
Add-Type -AssemblyName 'System.Windows.Forms'
function local:Wait {
param ($ms)
Start-Sleep -Milliseconds $ms
}
$k = [System.Windows.Forms.SendKeys]
function local:Send {
param ($keys)
$k::SendWait($keys)
}
function local:ResetTabPos {
Send '%(2)'
Wait 300
Send '%(1)'
Wait 300
Send '%(2)'
Wait 300
Send '%(1)'
}
Start-Process -FilePath 'ms-clock:'
Wait 1000
ResetTabPos
Wait 300
Send '+{TAB}' # Tab to new timer
Wait 300
Send ' ' # Click it
Wait 400
# Type hours
if ($PSBoundParameters.ContainsKey('Hours')) {
Send $Hours.ToString('f0')
}
elseif ($PSBoundParameters.ContainsKey('Time')) {
Send $Time.Hours.ToString('f0')
}
Wait 200
Send '{TAB}' # Next field
Wait 200
# Type minutes
if ($PSBoundParameters.ContainsKey('Minutes')) {
Send $Minutes.ToString('f0')
}
elseif ($PSBoundParameters.ContainsKey('Time')) {
Send $Time.Minutes.ToString('f0')
}
Wait 200
Send '{TAB}' # Next field
Wait 200
# Type seconds
if ($PSBoundParameters.ContainsKey('Seconds')) {
Send $Seconds.ToString('f0')
}
elseif ($PSBoundParameters.ContainsKey('Time')) {
Send $Time.Seconds.ToString('f0')
}
Wait 200
Send '{TAB}' # Next field
Wait 200
# Type name
if ($PSBoundParameters.ContainsKey('Name')) {
Send ($Name -replace '([%\+\^~\(\)\[\]\{\}])', '{$1}')
}
Wait 200
Send '{TAB}' # Highlight save button
Wait 200
Send ' ' # Click it
Wait 400
ResetTabPos
Wait 300
Send '{TAB 4}' # Tab into timers list
Wait 300
Send '{END}' # Go to last one (ours)
Wait 300
Send '{TAB}' # Highlight start button
Wait 300
Send ' ' # Click it
# Don't try this at work
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment