39

I cant seem to figure out how to create a new scheduled task that is triggered daily and repeats every 30 minutes. I have been going in circles.

Everything about this below works for setting the task I want, but only triggered once.

#Credentials to run task as
$username = "$env:USERDOMAIN\$env:USERNAME" #current user
$password = "notmypass"

#Location of Scripts:
$psscript = "C:\test\test.ps1"
$Sourcedir ="C:\testsource\"
$destdir = "C:\testdest\"
$archivepassword = "notmypass"


####### Create New Scheduled Task
$action = New-ScheduledTaskAction -Execute "Powershell" -Argument "-WindowStyle Hidden `"$psscript `'$sourcedir`' `'$destdir`' `'$archivepassword`'`""
$trigger = New-ScheduledTaskTrigger -Once -At 7am -RepetitionDuration  (New-TimeSpan -Days 1)  -RepetitionInterval  (New-TimeSpan -Minutes 30)
$settings = New-ScheduledTaskSettingsSet -Hidden -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable
$ST = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask EncryptSyncTEST -InputObject $ST -User $username -Password $password

If I change -Once to -Daily I lose the -RepetitionInterval flags. And if I come back to update the task to daily after registering it, it wipes the repeating trigger.

This isn't an uncommon scheduling method, and is easily applied through the task scheduler UI. I feel like it is probably simple but I am missing it.

Any help is appreciated.

EDIT: Addressing the duplicate question. The question in the post "Powershell v3 New-JobTrigger daily with repetition" is asking the same. But as I commented earlier, none of the answers solve the issue. The marked answer does exactly what I already have here, it sets a task with a -Once trigger, then updates it to repeat every 5 minutes for 1 day. After the first day that task will never be triggered again. It does not address the issue of triggering a task everyday with repetition and duration until the next trigger.

The other three answers on that post are also not addressing the question. I do not know why it was marked answered, because it is not correct. I fully explored those replies before I posted this question. With that post having aged and being marked as answered I created this question.

Note: I have found a workaround, but not a great one. At current it seems the easiest way to define custom triggers using powershell is to manipulate the Scheduled Task XML and import it directly using Register-ScheduledTask

Promise Preston
  • 24,334
  • 12
  • 145
  • 143
malexander
  • 4,522
  • 1
  • 31
  • 37

11 Answers11

29

While the PowerShell interface for scheduled task triggers is limited, it turns out if you set the RepetitionDuration to [System.TimeSpan]::MaxValue, it results in a duration of "Indefinitely".

$trigger = New-ScheduledTaskTrigger `
    -Once `
    -At (Get-Date) `
    -RepetitionInterval (New-TimeSpan -Minutes 5) `
    -RepetitionDuration ([System.TimeSpan]::MaxValue)

Tested on Windows Server 2012 R2 (PowerShell 4.0)

Shaddy Zeineddine
  • 467
  • 1
  • 5
  • 8
25

Create base trigger:

$t1 = New-ScheduledTaskTrigger -Daily -At 01:00

Create secondary trigger (omit -RepetitionDuration for an indefinite duration; be sure to use the same -At argument):

$t2 = New-ScheduledTaskTrigger -Once -At 01:00 `
        -RepetitionInterval (New-TimeSpan -Minutes 15) `
        -RepetitionDuration (New-TimeSpan -Hours 23 -Minutes 55)

Take repetition object from secondary, and insert it into base trigger:

$t1.Repetition = $t2.Repetition

Bob's your uncle:

New-ScheduledTask -Trigger $t1 -Action ...
mklement0
  • 382,024
  • 64
  • 607
  • 775
SteinIP
  • 376
  • 4
  • 5
23

Here is a way of creating a scheduled task in Powershell (v5 on my machine, YMMV) that will start at 12AM every day, and repeat hourly for the rest of the day. Therefore it will run indefinitely. I believe this is a superior approach vs setting -RepetitionDuration to ([timespan]::MaxValue) as I commented earlier, as the trigger will show up in the Task Scheduler as:

At 12:00 AM every day - After triggered, repeat every 30 minutes for a duration of 1 day.

Rather than the date on which the task was registered appearing in the trigger as approaches that use -Once -At 12am result in, create the trigger as a simple -Daily -At 12am, register the task then access some further properties on the tasks Triggers property;

$action = New-ScheduledTaskAction -Execute <YOUR ACTION HERE>
$trigger = New-ScheduledTaskTrigger -Daily -At 12am
$task = Register-ScheduledTask -TaskName "MyTask" -Trigger $trigger -Action $action
$task.Triggers.Repetition.Duration = "P1D" //Repeat for a duration of one day
$task.Triggers.Repetition.Interval = "PT30M" //Repeat every 30 minutes, use PT1H for every hour
$task | Set-ScheduledTask
//At this point the Task Scheduler will have the desirable description of the trigger.
James Webster
  • 4,046
  • 29
  • 41
  • 2
    I've tried this method you suggested, and it doesn't produce the expected results. When I verified the trigger in the GUI, it shows a Daily trigger which executes at midnight and does not repeat. This was tested on Windows Server 2012 R2 Standard. – Shaddy Zeineddine Dec 21 '15 at 17:39
  • 2
    I just tried this and the concept did work fine for me, I was able to set `$task.Triggers.Repetition.Duration`, `$task.Triggers.Repetition.Interval`, and `$task.Triggers[0].ExecutionTimeLimit` to values I wanted and then run `$task | Set-ScheduledTask` and see repeat task every x set properly in the GUI. PS V5 on Win 8.1 – Chris Magnuson Jul 19 '16 at 13:21
  • When PT14M is used for 14 minutes repetition and to start at 16:05:00 the next run time is increasing by 14 seconds everytime.. the next run, instead of 16:19:00, is set to 16:19:14.. As such with every 14 minutes the repetition is increasing by 14 seconds.. Noticed this on Win 2012 SP1.. – Baskar Lingam Ramachandran Dec 05 '17 at 15:45
  • 1
    Rather than using the ISO8601 formatted time values directly (i.e. `P1D`, `PT30M`), you can use TimeSpan values by doing `[System.Xml.XmlConvert]::ToString($timespan)`, as mentioned at https://stackoverflow.com/a/2906063/602585 – deadlydog Feb 08 '18 at 05:15
  • This looked like it worked for me in the UI. Everything was good. Then I ran the task and got error 0x80070002. No matter what combination of anything I used, any time I edited the configuration of a task that was almost right, by way of Set-ScheduledTask, the task switched to having that error. Editing back to *exactly* the state before could restore function. – Lamarth Aug 23 '18 at 06:47
13

I'm sure there must be a better way, but this is my current workaround.

I created a task with the triggers I wanted then grabbed the XML it generated.

Below I am creating the task, then pulling the XML for that new task, replacing my triggers, then un-registering the task it and re-registering it with the updated XML.

Long term, I will probably just use the full XML file for the task and replace the strings as needed, but this works for now.

#Credentials to run task as
$username = "$env:USERDOMAIN\$env:USERNAME" #current user
$password = "notmypass"

#Location of Scripts:
$psscript = "C:\test\test.ps1"
$Sourcedir ="C:\testsource\"
$destdir = "C:\testdest\"
$archivepassword = "notmypass"

####### Create New Scheduled Task
$action = New-ScheduledTaskAction -Execute "Powershell" -Argument "-WindowStyle Hidden '$EncryptSync' '$sourcedir' '$destdir' '$archivepassword'"
$trigger = New-ScheduledTaskTrigger -Once -At 7am -RepetitionDuration  (New-TimeSpan -Days 1)  -RepetitionInterval  (New-TimeSpan -Minutes 30)
$settings = New-ScheduledTaskSettingsSet -Hidden -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable
$ST = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
Register-ScheduledTask "EncryptSyncTEST" -InputObject $ST -User $username -Password $password


[xml]$EncryptSyncST = Export-ScheduledTask "EncryptSyncTEST"
$UpdatedXML = [xml]'<CalendarTrigger xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"><Repetition><Interval>PT30M</Interval><Duration>P1D</Duration><StopAtDurationEnd>false</StopAtDurationEnd></Repetition><StartBoundary>2013-11-18T07:07:15</StartBoundary><Enabled>true</Enabled><ScheduleByDay><DaysInterval>1</DaysInterval></ScheduleByDay></CalendarTrigger>'
$EncryptSyncST.Task.Triggers.InnerXml = $UpdatedXML.InnerXML

Unregister-ScheduledTask "EncryptSyncTEST" -Confirm:$false
Register-ScheduledTask "EncryptSyncTEST" -Xml $EncryptSyncST.OuterXml -User $username -Password $password
MonkeyDreamzzz
  • 3,978
  • 1
  • 39
  • 36
malexander
  • 4,522
  • 1
  • 31
  • 37
  • 1
    Change -RepetitionInterval to a number of days that fits your need. You can, for example, put 3000 for near 10 years of repetition. Ex.: $trigger = New-ScheduledTaskTrigger -Once -At 7am -RepetitionDuration (New-TimeSpan -Days 3000) -RepetitionInterval (New-TimeSpan -Minutes 30) – Benoit Drapeau Sep 19 '14 at 11:18
  • 3
    It looks like your workaround is the way to go, at least from what I can tell. The documentation [here](http://technet.microsoft.com/en-us/library/jj649821.aspx) lists the -RepetitionInterval parameter to be incompatible (different parameter set) with the -Daily option... It only works for the -Once... Either I am missing something, or someone fell asleep when they were defining the parameter sets in the cmdlet... :( – CRCerr0r Jan 12 '15 at 18:46
  • 4
    You can also set `-RepetitionDuration` to `([timespan]::MaxValue)`; this will show up in the Task Scheduler as 'After triggered, repeat every X indefinitely'. – James Webster Sep 28 '15 at 06:12
  • 1
    I'm finding `[timespan]::MaxValue` is bugged on Windows Server 2016. The `New-ScheduledTaskTrigger` cmdlet is successful, but `Register-ScheduledTask` complains about the value. "incorrectly formatted or out of range". – Patrick Jan 30 '18 at 10:27
  • Your thought of just loading an xml file is the best approach in my opinion. We store it as a file but it could be in a variable and substitute a placeholder and do a string replace on those before calling Register-ScheduledTask to have the task created. Obtaining the xml file is as simple as creating the task the way you want it in the scheduler then right click and export... – Action Dan May 18 '19 at 20:23
8

The easiest method I found to accomplish this is to use schtasks.exe. See full documentation at https://msdn.microsoft.com/en-us/library/windows/desktop/bb736357%28v=vs.85%29.aspx

schtasks.exe /CREATE /SC DAILY /MO 1 /TN 'task name' /TR 'powershell.exe C:\test.ps1' /ST 07:00 /RI 30 /DU 24:00

This creates a task that runs daily, repeats every 30 minutes, for a duration of 1 day.

llamb
  • 191
  • 2
  • 3
5

https://stackoverflow.com/a/54674840/9673214 @SteinIP solution worked for me with slight modification

In 'create secondary trigger' part added '-At' parameter with same value as in 'create base trigger' part.

Create base trigger

$t1 = New-ScheduledTaskTrigger -Daily -At 01:00

Create secondary trigger:

$t2 = New-ScheduledTaskTrigger -Once -RepetitionInterval (New-TimeSpan -Minutes 15) -RepetitionDuration (New-TimeSpan -Hours 23 -Minutes 55) -At 01:00

Do the magic:

$t1.Repetition = $t2.Repetition

New-ScheduledTask -Trigger $t1 -Action ...
Arun Pant
  • 116
  • 1
  • 4
4

Another way to do it is just to create multiple triggers like so:

$startTimes     = @("12:30am","6am","9am","12pm","3pm","6pm")
$triggers = @()
foreach ( $startTime in $startTimes )
{
    $trigger = New-ScheduledTaskTrigger -Daily -At $startTime -RandomDelay (New-TimeSpan -Minutes $jitter)
    $triggers += $trigger
}
  • This way works when requiring a task to be run throughout the day (or recurring time frame) and avoids the condition where a single recurring trigger with repeating value is not triggered at the initial time and fails to repeat at the expected future intervals. e.g. Thanks to powershell creating hourly triggers for _must run_ tasks is much easier. – AKi Nov 22 '17 at 15:29
  • And on the flip side, you'd have ended up cluttering the Scheduled Tasks environment with HALF A DOZEN DIFFERENT TASKS, perhaps more! – Ifedi Okonkwo Aug 21 '18 at 11:59
3

If you wanna a infinate Task duration on Windows 10 just use this (Do not specify -RepetitionDuration)

$action = New-ScheduledTaskAction -Execute (Resolve-Path '.\main.exe')
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Hours 1)

Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "GettingDataFromDB" -Description "Dump of new data every hour"
  • Will this keep being scheduled and run after a reboot or re-logon? – Zoltán Tamási Sep 12 '19 at 09:15
  • Yes, the tasks are saved in the special folder. You can refer to this docs https://learn.microsoft.com/en-us/windows/win32/taskschd/tasks – Dawid Kisielewski Sep 17 '19 at 08:09
  • Not sure this actually runs after a reboot, because the task is triggered only once. After a reboot, there is no reason to trigger this task again. There is a known issue of scheduled tasks not running after a reboot. – AMissico Jun 18 '20 at 12:53
2

Here's another variation that seems to work well for this old chestnut, but is less complex than some of the other solutions. It has been tested on Server 2012 R2, Server 2016 and Server 2019, with the default PS version on each OS. "Merging" the triggers didn't work for me on 2012. Didn't bother with the others.

The steps are simple:

  1. Create the scheduled task with the basic schedule first
  2. Extract the details from the new task
  3. Modify the trigger repetition/duration
  4. Update the existing task with the modified version

The example consists of a daily task that repeats every hour for a day (I've set it to 23 hours to make the date/time syntax a little clearer). The same timespan format is used for Duration and Interval.

# create the basic task trigger and scheduled task
$trigger = New-ScheduledTaskTrigger -Daily -At 15:55
$Settings = New-ScheduledTaskSettingsSet –StartWhenAvailable
Register-ScheduledTask -TaskName $TaskName -Trigger $Trigger -Action $Action -Setting $Settings -User $User

# Get the registered task parameters
$task = Get-Scheduledtask $TaskName

# Update the trigger parameters to the repetition intervals
$task.Triggers[0].Repetition.Duration = "P0DT23H0M0S"
$task.Triggers[0].Repetition.Interval = "P0DT1H0M0S"

# Commit the changes to the existing task
Set-ScheduledTask $task

Note that if your task has multiple triggers - although that'd be unusual if you have a repetition interval - you need to modify whichever trigger needs the repetitions. The example only has a single trigger, so we just select the first (and only) member of the list of triggers - $task.Triggers[0]

The timespan is ISO 8601 format - it's a string with no spaces. The required numeric value precedes the time designation (e.g. 1H for one hour, not H1). The string must contain all the time designations as listed, with a 0 substituting for any empty values. The P ("period") at the beginning indicates it's a duration rather than a timestamp.

P(eriod)0D(ays)T(ime)0H(ours)0M(inutes)0S(econds)
P0DT1H0M0S  = 0 days, 1 hours, 0 minutes, 0 seconds
P0DT0H15M30S = 0 days, 0 hours, 15 minutes, 30 seconds

You can use a similar method to modify the trigger if you want to change a start time on a task. This applies to -Once or -Daily tasks.

$task = Get-ScheduledTask $taskname
$d = ([DateTime]::now).tostring("s")  # 2021-11-30T17:39:31
$task.Triggers[0].StartBoundary = $d
Set-ScheduledTask $task
LeeM
  • 1,118
  • 8
  • 18
0

Old question and I'm not sure if the powershell cmdlets are a requirement. But I just use schtasks.

If you want to run every 15 minutes:

schtasks /f /create /tn taskname `
    /tr "powershell c:\job.ps1" /ru system `
    /sc minute /mo 15 /sd 01/01/2001 /st 00:00

This will 'trigger' on 1/1/2001 midnight and run every 15 minutes. so if you create it today, it'll just run on the next event interval.

If you want it to 'trigger' every single day, you can do this:

schtasks /f /create /tn taskname `
    /tr "powershell c:\job.ps1" /ru system `
    /sc daily /sd 01/01/2001 /st 10:00 /du 12:14 /ri 15

This will 'trigger' on 1/1/2001 10am, and run every 15 minutes for 12 hours and 14 minutes. so if you start it today, it'll just run on the next event interval.

I normally run my 'every 15 minutes' like the top one and my 'every day for x times' like the bottom. So if i need to run something at say 10am and 2pm, i just change the /du on the second one to 5 hours and the /ri to 4. then it repeates every 4 hours, but only for 5 hours. Technically you may be able to put it at 4:01 for duration, but i generally give it an hour to be safe.

I used to use the task.xml method and was having a really tough time with the second scenario until I noticed in a task.xml that was exported it basically just has something like this below.

<Triggers>
    <CalendarTrigger>
      <Repetition>
        <Interval>PT3H</Interval>
        <Duration>PT15H</Duration>
        <StopAtDurationEnd>false</StopAtDurationEnd>
      </Repetition>
      <StartBoundary>2017-11-27T05:45:00</StartBoundary>
      <ExecutionTimeLimit>PT10M</ExecutionTimeLimit>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>

This was for a job that ran every 3 hours between 5:45 and 7:45. So I just fed the interval and duration into a daily schedule command and it worked fine. I just use an old date for standardization. I'm guessing you could always start it today and then it would work the same.

To run this on remote servers I use something like this:

$sb = { param($p); schtasks /f /create /tn `"$p`" /tr `"powershell c:\jobs\$p\job.ps1`" /ru system /sc daily /sd 01/01/2001 /st 06:00 /du 10:00 /ri (8*60) } }
Invoke-Command -ComputerName "server1" -ScriptBlock $sb -ArgumentList "job1"
Roy Ashbrook
  • 814
  • 8
  • 14
-2

Working in Windows 10

Set-ExecutionPolicy RemoteSigned

$action=New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '‪C:\Users\hp\Anaconda3\python.exe ‪C:\Users\hp\Desktop\py.py'
$trigger = New-ScheduledTaskTrigger `
    -Once `
    -At (Get-Date) `
    -RepetitionInterval (New-TimeSpan -Minutes 15) `
    -RepetitionDuration (New-TimeSpan -Days (365 * 20))
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "ts2" -Description "tsspeech2" 
Harshal SG
  • 403
  • 3
  • 7