Randomizing Scheduled Tasks Start Times in Windows
It may be useful to stagger some scheduled tasks to reduce network bandwith. This is easy enough to do in the GUI, (right click a task, select properties, triggers, edit, delay task . . .) but that takes times and alot of clicks.
PowerShell can do it faster!
Let’s start with the basic syntax to schedule a task for 3am Sunday.
#Create scheduled task
Unregister-ScheduledTask -TaskName "choco_software_update" -Confirm:$false
$action = New-ScheduledTaskAction -Execute 'choco' -Argument 'upgrade all -a'
$trigger = @(
$(New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 -DaysOfWeek Sunday -At 3am)
)
New-ScheduledTaskPrincipal -UserId chocoUpdater -RunLevel Highest
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "chocoUpdate" -Description "Daily checks for software updates." -user $user -password $password -RunLevel Highest
This will work, but all our PCs will send network traffic a the the same time. “-RandomDelay” can solve this. This will set the same schedule but with a random delay of one hour:
$trigger = @(
$(New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 -DaysOfWeek Sunday -At 3am -RandomDelay (New-TimeSpan -Hour 1)
)
Options for “-RandomDelay” are “Second,” “Minute,” “Hour,” “Day.” The plural of each will work the same: “Seconds,” “Minutes,” “Hours,” “Days.”
Another option is to use a random variable to set the task trigger. PowerShell can generate a random number easily enough, (Get-Random -Minimum 0 -Maximum 12), but then we need to convert to a sting and concatenate with “am” or “pm”–do-able, but getting a random item in an array feels simpler.
$hours = @("1am", "2am", "3am", "4am", "5am", "6am", "7am", "8am", "9am", "10am", "11am", "1pm", "2pm", "3pm", "4pm", "5pm", "6pm", "7pm", "8pm","9pm", "10pm", "11pm")
$rand_hour = (Get-Random -InputObject $hours -Count 1)
$trigger = @(
$(New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 -DaysOfWeek $rand_day -At $rand_hour)
)
This will set a task to run once a week at a random hour on a random day. We can do the same for a daily run task at a random hour.
$days = @("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
$rand_day = (Get-Random -InputObject $days -Count 1)
$hours = @("1am", "2am", "3am", "4am", "5am", "6am", "7am", "8am", "9am", "10am", "11am", "1pm", "2pm", "3pm", "4pm", "5pm", "6pm", "7pm", "8pm","9pm", "10pm", "11pm")
$rand_hour = (Get-Random -InputObject $hours -Count 1)
$trigger = @(
$(New-ScheduledTaskTrigger -Weekly -WeeksInterval 1 -DaysOfWeek $rand_day -At $rand_hour)
)
I use an array for the trigger, becuase it makes it easy to reuse the same code and add additional triggers. This would work just as well in the above:
$trigger = New-ScheduledTaskTrigger -At $rand_hour -Daily
But if we want to add additional triggers:
$trigger = @(
$(New-ScheduledTaskTrigger -At $rand_hour -Daily)
$(New-ScheduledTaskTrigger -At $rand_hour -Daily)
)
We can also run a task every other week (or every third, etc.) with a single line by adjusting the “-WeeksInterval.”
$trigger = @(
$(New-ScheduledTaskTrigger -Weekly -WeeksInterval 2 -DaysOfWeek $rand_day -At $rand_hour)
)
In addition to daily and weekly, a task can be scheduled for run once.
For “-Once” be aware of how to format the date and time.
$trigger = @(
New-ScheduledTaskTrigger -Once -At "8/31/2018 8:56:57 AM"
)
There are lots of other options you can see from the “Get-Help New-ScheduledTaskTrigger” cmdlet.
NAME
New-ScheduledTaskTrigger
SYNTAX
New-ScheduledTaskTrigger [-Once] -At <datetime> [-RandomDelay <timespan>] [-RepetitionDuration <timespan>] [-RepetitionInterval
<timespan>] [-CimSession <CimSession[]>] [-ThrottleLimit <int>] [-AsJob] [<CommonParameters>]
New-ScheduledTaskTrigger [-Daily] -At <datetime> [-DaysInterval <uint32>] [-RandomDelay <timespan>] [-CimSession <CimSession[]>]
[-ThrottleLimit <int>] [-AsJob] [<CommonParameters>]
New-ScheduledTaskTrigger [-Weekly] -At <datetime> [-RandomDelay <timespan>] [-DaysOfWeek {Sunday | Monday | Tuesday | Wednesday
| Thursday | Friday | Saturday}] [-WeeksInterval <uint32>] [-CimSession <CimSession[]>] [-ThrottleLimit <int>] [-AsJob]
[<CommonParameters>]
New-ScheduledTaskTrigger [-AtStartup] [-RandomDelay <timespan>] [-CimSession <CimSession[]>] [-ThrottleLimit <int>] [-AsJob]
[<CommonParameters>]
New-ScheduledTaskTrigger [-AtLogOn] [-RandomDelay <timespan>] [-User <string>] [-CimSession <CimSession[]>] [-ThrottleLimit
<int>] [-AsJob] [<CommonParameters>]
Further Reading:
https://docs.microsoft.com/en-us/powershell/module/scheduledtasks/new-scheduledtasktrigger?view=win10-ps
https://community.spiceworks.com/topic/2159322-new-scheduledtasktrigger-date-time-formatting
https://ss64.com/ps/scheduler.html