I am trying to use Task Scheduler to run a PS1 script, however it does not seem to work. When I run the task PowerShell opens briefly, but the script does not run. When I execute the script manually it runs as expected.
Start a Program
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
D:\Powershell\test.ps1
Win10
Script:
Add-Type -AssemblyName System.Windows.Forms
$Timer = [System.Timers.Timer]::new(3000)
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action{
[System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
}
$Timer.Start()
Is there anything I am missing here?
As in my comment, to execute a script (*.ps1
) you just need to call the -File
Argument or -f
for short however, doing only this, will not result in what you want (a task that is Alt-Tabbing indefinitely?) because the task would end as soon as the ObjectEvent
was registered.
As a workaround, you need to find a way to keep the scheduled task alive, ergo, keep the powershell.exe
process running in the background alive.
I'll list a few option so you can decide which one you like more or fits your need.
The easiest one, in my opinion, is just to add the -NoExit
argument to your task, this will keep the task alive indefinitely, until, manually ending it / reboot / shutdown / killing the powershell.exe
process / etc.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-WindowStyle Hidden -NoExit -f "D:\testing\script.ps1"
Adding a loop on the code, for this you have many options, for exampleGet-EventSubscriber | Wait-Event
which, same as before, will keep the task alive indefinitely.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-WindowStyle Hidden -f "D:\testing\script.ps1"
Add-Type -AssemblyName System.Windows.Forms
$Timer = [System.Timers.Timer]::new(3000)
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action {
[System.Windows.Forms.SendKeys]::SendWait('%{TAB}')
}
$Timer.Start()
Get-EventSubscriber | Wait-Event
A loop that would keep the task alive for X
days / hours / minutes:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-WindowStyle Hidden -f "D:\testing\script.ps1"
[datetime]
object instead of [System.Diagnostics.Stopwatch]
here, your call):Add-Type -AssemblyName System.Windows.Forms
$Timer = [System.Timers.Timer]::new(3000)
Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action {
[System.Windows.Forms.SendKeys]::SendWait('%{TAB}')
}
$Timer.Start()
$elapsed = [System.Diagnostics.Stopwatch]::StartNew()
do {
Start-Sleep -Milliseconds 5
}
until($elapsed.Elapsed.Minutes -ge 60)
$elapsed.Stop()
exit 0
Last one, similar to the example before but not using an ObjectEvent
at all:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-WindowStyle Hidden -f "D:\testing\script.ps1"
Add-Type -AssemblyName System.Windows.Forms
$elapsed = [System.Diagnostics.Stopwatch]::StartNew()
do {
[System.Windows.Forms.SendKeys]::SendWait('%{TAB}')
Start-Sleep -Milliseconds 3000
}
until($elapsed.Elapsed.Seconds -ge 30)
$elapsed.Stop()
exit 0