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.

scheduled tasks

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