0

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.

  • Task Scheduler settings:
    • Action: Start a Program
    • Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    • Arguments: D:\Powershell\test.ps1
    • Configure for: 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?

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
hcsuaf
  • 3
  • 1
  • 3
    Arguments: `D:\Powershell\test.ps1` should be `-f "D:\Powershell\test.ps1"` tho, if this is running as `NT AUTHORITY\SYSTEM` I don't think it will work – Santiago Squarzon Aug 12 '21 at 21:09
  • If the task runs under the **SYSTEM** account (add that detail to the question), [test whether it actually works under the system account](https://stackoverflow.com/a/51612478/1701026). Also add `-ExecutionPolicy bypass`. – iRon Aug 13 '21 at 07:41

1 Answers1

0

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, imo, 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.

    • Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    • Arguments: -WindowStyle Hidden -NoExit -f "D:\testing\script.ps1"
  • Adding a loop on the code, for this you have many options, for example
    Get-EventSubscriber | Wait-Event which, same as before, will keep the task alive indefinitely.

    • Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    • Arguments: -WindowStyle Hidden -f "D:\testing\script.ps1"
    • Code:
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:
    • Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    • Arguments: -WindowStyle Hidden -f "D:\testing\script.ps1"
    • Code (you can use a [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:
    • Program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    • Arguments: -WindowStyle Hidden -f "D:\testing\script.ps1"
    • Code:
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
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • 1
    I was able to make this work using your suggestions, thank you for this! The task of alt+tabbing indefinitely was just an easy way for me to identify if the loop was actually running continuously. I really wanted to work through the process of scheduling a task that occurs when the computer goes idle - and in some situation use a loop to continue to do something until interruption. – hcsuaf Aug 18 '21 at 19:53
  • @hcsuaf if the answer was helpful to you considerer [accepting it](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) – Santiago Squarzon Aug 18 '21 at 19:55