powershellscheduled-taskspowershell-5.1

Create a Scheduled Task that runs the first of every month


Question: How do I tweak this script to allow me to schedule the task to fire on the first of every month?

My script is below and I'm trying to schedule a monthly task that kicks off the 1st of every month. Technically, my code works; it creates a job that runs on a certain day, every four weeks. But I'd rather it run on a certain date so that, when we get down-alerts for our servers, we know it's the scheduled task.

# As of this time, PS v5.1 has no easy way to choose a schedule like "the first of every month."
# Below is the closest I can get to a monthly schedule but it's strictly based on number of weeks.
$ErrorActionPreference = "SilentlyContinue"

$ScheduledTaskActions = @{
    Execute  = "powershell.exe"
    Argument = "Restart-Computer -Force"
}

$TaskAction = New-ScheduledTaskAction @ScheduledTaskActions

$ScheduledTaskParameters = @{
    TaskName = "Restart Computer - Monthly"
    Trigger = New-ScheduledTaskTrigger -At "00:00" -Weekly -WeeksInterval "4" -DaysOfWeek "Monday"
    Action = $TaskAction
    User = "NT Authority\System"
    Runlevel = "Highest"
    Description = "Reboots the machine every four weeks."
}

Register-ScheduledTask @ScheduledTaskParameters

Basically, what the aforementioned code generates a trigger that looks like this in Task Scheduler but, again, I want something that actually runs on the first of every month.

enter image description here

This is what I need: enter image description here

In my mind, I figured I could do something like $trigger = $triggers.Create(4) to make it a monthly thing but, even after poking around some of the MS articles that were linked to the aforementioned questions, I don't know where to drop that code into place; it looks like it's not technically PS code in those MS pages.

I found Create monthly trigger for Scheduled Task in Powershell (With additional criteria) and Powershell for Creating a scheduled task in which runs monthly but I still don't fully understand how they got something working. I don't know if they just didn't have a full example or if I'm just not able to decipher how they got it working.

Updated Script

Thanks to the help of MisterSmith, this is what I'm currently using. In my testing it seems to work fine! I changed the date variable $Date.Day -le "27" and the day variable to $Date.DayOfWeek -eq "Wednesday" and then manually kicked off the task after creation. The machine bounced as expected. I then reverted those changes and recreated the task so that it'll fire the first Monday of every month. From the machine's point of view, the task is cryptic but, it's spawned from our RMM so, I don't worry about how it looks - so long as my teammates can read and make sense of the code.

$ErrorActionPreference = "SilentlyContinue"
# Command that does the work.
$Command = {
    $Date = Get-Date
    if(($Date.Day -le "7") -and ($Date.DayOfWeek -eq "Monday")){
        Restart-Computer -Force
    }
}

# Convert the command block above to a Base64-encoded command so it can be easily added to a scheduled task.
$Base64Command = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($Command))

## Creating the Scheduled Task.
# Hash table for task's command and arguments; in this case, the argument is the Base64-encoded command from above.
$ScheduledTaskActions = @{
    Execute = "powershell.exe"
    Argument = "-EncodedCommand $Base64Command"
}

# Variable for the task's action.
$TaskAction = New-ScheduledTaskAction @ScheduledTaskActions

# Hash table for parameters used by Register-ScheduledTask.
$ScheduledTaskParameters = @{
    TaskName = "Restart Computer - First Monday of Every Month"
    Trigger = New-ScheduledTaskTrigger -At "00:30" -Weekly -DaysOfWeek "Monday"
    Action = $TaskAction
    User = "NT Authority\System"
    Runlevel = "Highest"
    Description = "Reboots the machine on the first Monday of every month."
}

# Registering the new task with all the settings above.
Register-ScheduledTask @ScheduledTaskParameters -Force

How it looks in Windows Task Scheduler: Triggers: The Triggers

Trigger details: Trigger details

Actions: The Actions


Solution

  • A strait PowerShell method is to execute a script every Monday in Task Scheduler, then in PowerShell decide if its the 1st Monday of the month or not and restart as required.

    Update your action to call the file instead of Restart-Computer directly.

    $ScheduledTaskActions = @{
      Execute  = "powershell.exe"
      Argument = '-File C:\path\to\your\restart-script.ps1'
    }
    

    Create restart-script.ps1 somewhere with the below. It should only shutdown if Today is a Monday and within the first 7 days of the month, otherwise it does nothing:

    $d = Get-Date;
    if(($d.Day -le 7) -and ($d.DayOfWeek -eq 'Monday')){
      Restart-Computer -Force
    }
    

    Finally, run the script every Monday:

    $Trigger = New-ScheduledTaskTrigger -At "00:00" -Weekly -DaysOfWeek "Monday"
    

    If you really dont want to deal with managing restart-script.ps1 / really want it all contained in task manager script you could convert the above script to unicode bytes and wrap in a base64 string and pass it to powershell with powershell -EncodedCommand [BASE64_STRING_ENCODED_UNICODE_BYTES]. (its kinda ugly/suspicious looking looking but its more contained)