'Powershell: Scheduled Task with Daily Trigger and Repetition Interval
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
Solution 1:[1]
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
Solution 2:[2]
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)
Solution 3:[3]
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.
Solution 4:[4]
Create base trigger:
$t1 = New-ScheduledTaskTrigger -Daily -At 01:00
Create secondary trigger (omit -RepetitionDuration for an indefinite duration):
$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 ...
Solution 5:[5]
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.
Solution 6:[6]
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
}
Solution 7:[7]
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 ...
Solution 8:[8]
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"
Solution 9:[9]
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:
- Create the scheduled task with the basic schedule first
- Extract the details from the new task
- Modify the trigger repetition/duration
- 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
Solution 10:[10]
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"
Solution 11:[11]
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"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
