Use PowerShell to Create Scheduled Tasks


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to create a scheduled task.

Microsoft Scripting Guy, Ed Wilson, is here. Today, it is cold, wet, and rainy—not exactly my favorite combination. In fact, I would rather have snow. At least then there would be an excuse for the dreariness. Oh well. Snow in the deep south is about as rare as—well…as rare as people who enjoy manually creating scheduled tasks.

Dude, creating scheduled tasks is boring. Not only that, it is easy to make a mistake. And when I am done creating a scheduled task, I am not really sure what it is going to do until it runs (or does not run) at the next scheduled time.

When I was consulting, I hated creating scheduled tasks because if I messed up, I had to drive across town to try to troubleshoot the thing. Often, my code was simply missing a comma, a quotation mark, or a space. Mistakes like that mean you cannot really bill the customer for it, which becomes a double whammy—the lost time and the lost billing. Luckily, with Windows PowerShell, it is much easier.

Note  The Scheduled Task module first appeared with Windows PowerShell 3.0 in Windows 8 and Windows Server 2012.

There are a few things that are required when it comes to creating a schedule task. One of these things is the action. What do I want the scheduled task to do? Without specifying an action, there is no reason to create a scheduled task.

Not only is this a requirement, but it can also be really frustrating. I need to get it exactly right. The graphical form can provide some clues. Here is the form for creating a new scheduled task action:

Image of menu

The action that I want is to start a program. In the New-ScheduledTaskAction cmdlet, this is the –Execute parameter, and I specify the name of the program I want to run. For me, that generally translates to PowerShell.exe. The Add arguments box translates to the –Argument parameter. For me, this is everything I want to pass to the PowerShell.exe command. The Start in box translates to the –WorkingDirectory parameter of the cmdlet.

The hardest parameters to figure out are ­Execute and Argument. But I use the Run dialog box to see if I have my command working properly. Because the Run dialog box is not resizable (in fact, it doesn’t even scroll), it is frustrating to use.

So I type my commands in Notepad until I have something that works the way I want it to. Typing the command in Notepad provides me the chance to scroll and see exactly what I am typing, and it provides a convenient way for me to store my working command for later reference and reuse. In addition, by using Notepad, I can work with a long command and then use CTRL-A and CTRL-C to select and copy my command. I then use CTRL-V to paste it into the Run dialog box.

By directly executing my command line, I can fine tune the command easily and quickly. Following is the command I decided to use. (This is a single-line command that wraps in this post.)

Powershell -NoProfile -WindowStyle Hidden -command "& {get-eventlog -logname Application -After ((get-date).AddDays(-1)) | Export-Csv -Path c:\fso\applog.csv -Force -NoTypeInformation}"

I need to break-up the command for the Execute and Argument parameters. If I do not do this, when the scheduled task runs, an error message will pop up and ask me how I want to execute the program. Frustrating, but hey, not a biggie. Here is the command from my Windows PowerShell script:

$action = New-ScheduledTaskAction -Execute 'Powershell.exe' `

  -Argument '-NoProfile -WindowStyle Hidden -command "& {get-eventlog -logname Application -After ((get-date).AddDays(-1)) | Export-Csv -Path c:\fso\applog.csv -Force -NoTypeInformation}"'

Now I create a trigger. I want the command to run each day at 9:00 A.M. so that it will dump the previous day's events from the application log. To create the new trigger, I use the New-ScheduledTaskTrigger cmdlet:

$trigger =  New-ScheduledTaskTrigger -Daily -At 9am

One thing that is a bit confusing is that if I want my scheduled task to run, I need to register it. So, rather than using the New-ScheduledTask cmdlet, I use the Register-ScheduledTask cmdlet. I also provide it a name and a description, for example:

Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "AppLog" -Description "Daily dump of Applog"

When I do this, it creates the new scheduled task, and it marks it as ready to execute. I can see it in the Task Scheduler GUI tool in the root folder. The task is shown here:

Image of menu

Following is the complete script:

$action = New-ScheduledTaskAction -Execute 'Powershell.exe' `

  -Argument '-NoProfile -WindowStyle Hidden -command "& {get-eventlog -logname Application -After ((get-date).AddDays(-1)) | Export-Csv -Path c:\fso\applog.csv -Force -NoTypeInformation}"'

$trigger =  New-ScheduledTaskTrigger -Daily -At 9am

Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "AppLog" -Description "Daily dump of Applog"

Here are several things to keep in mind:

  • This script requires admin rights to create a new scheduled task.
  • The script will run in the context of the user who created the scheduled task.
  • The script uses absolute paths for the output CSV file.
  • The script overwrites all existing CSV files with the same name.
  • Be very careful with spaces in the argument portion of the script. It may look like it will work, but it might not if you press ENTER to break up the line of code.
  • The previous script is three lines of code, but I added a line break for the first line of code.

The script is shown here inside the Windows PowerShell ISE:

Image of command output

That is all there is to creating and registering a new scheduled task with Windows PowerShell. Scheduled Task Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Comments (19)

  1. Anonymous says:

    Hi,

    This script looks very much what i am looking for, if you could help me with my requirement it will be great

    a powershell script ( script A)will be deployed to end user computer and it should setup a schedule Task to Run another powershell script ( Script B) at a periodic interval ( every 6 hours).

    Thank you

  2. John G says:

    Exactly what I was looking for to automate a startup task on several new servers!

  3. Jan C says:

    Excellent starting point. Thank You. I did however run into a few problems with the PowerShell cmdlets. Would you know how to set EndBoundary on a Trigger? This is required to setup a task to auto-delete after expiration time.

  4. Sathishg1 says:

    I have doubt in that.

    I wanted to run some other power shell script located in a directory. For that I need to mention that directory at start in (optional) area.

    Where and what do I need to write in the script . Please help me on that.

  5. Jason says:

    How do I use Powershell to create a scheduled task that is marked as ‘Configured for: Windows Server 2012" in the Task Scheduler? Currently my script is building the Windows 7 / Windows 2008 tasks.

  6. Ganesan says:

    Hi,
    I am unable to see the cmdlet New-ScheduledTask in PS 3. Which version of PS of this?

  7. charles says:

    Hey Ed,

    Can this script be deployed via SCCM to a server/s to create the task schedule locally on the server it is deployed to???
    Thanks!!!

  8. Loek Plevier says:

    Hi,

    How do I get these cmdlets ? I do not have windows server 2012. Is this usable in windows server 2008 r2 and does it work with server 2003 2008 and 2012 ?

  9. Enda says:

    Great article as always Ed, keep up the good work!

  10. Britv8.com says:

    Hi Ed!
    How do I modify the scheduled task to "run whether user logged in or not" By default it only creates a task that will run when the user is logged in? I was using this
    $STPrin = New-ScheduledTaskPrincipal -UserId domainserviceaccount -LogonType ServiceAccount -RunLevel Highest

    but there seems no option for this?

  11. Jean-Pierre Fouche says:

    Doesn’t work for me on Windows 7 with Powershell 3.
    Doesn’t work for me on Windows 7 with Powershell 4.
    I have trawled the internet looking for an extra download, but find none.
    Any ideas, please?
    Thanks
    Jean-Pierre

  12. GCC_CSS says:

    Hi Ed! Thanks for teaching me so much PowerShell through your blog. I’ve got a question I couldn’t find an answer to after quite a bit of searching, so I’m hoping you can shed some light.
    I’ve written some functions to create and remove scheduled tasks for various purposes, and these work fine on Windows 8.1. I’ve got a Win 10 system, and MOST of the commands work, but New-ScheduledTaskTrigger seems to have an issue. When I specify -Once -At
    , I get:

    New-ScheduledTaskTrigger : Method "NewTriggerByOnce" not found
    At line:1 char:10
    + $Trigger=New-ScheduledTaskTrigger -Once -At $ExecuteRemoveAt
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (PS_ScheduledTask:Root/Microsoft/…S_ScheduledTask) [New-ScheduledTaskT
    rigger], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041002,New-ScheduledTaskTrigger

    If I try get-help new-scheduledTaskTrigger, I get the expected brief list, including one that shows -Once:

    New-ScheduledTaskTrigger [-Once] -At [-RandomDelay ] [-RepetitionDuration ]
    [-RepetitionInterval ] [-CimSession ] [-ThrottleLimit ] [-AsJob] []

    However, when I try for examples, although Windows 8.1/PS4 gives me five nice examples, in PS5, I’m only seeing:

    NAME
    New-ScheduledTaskTrigger

    ALIASES
    None

    REMARKS
    Get-Help cannot find the Help files for this cmdlet on this computer. It is displaying only partial help.
    — To download and install Help files for the module that includes this cmdlet, use Update-Help.

    …and that is AFTER I’ve done Update-Help.

    I’m thinking this part of PS5 is broke, but I wouldn’t want to make any unfounded accusations! Any chance you might be able to shed some light?
    Relevant info:
    Name Value
    —- —–
    PSVersion 5.0.10586.0
    PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
    BuildVersion 10.0.10586.0
    CLRVersion 4.0.30319.42000
    WSManStackVersion 3.0
    PSRemotingProtocolVersion 2.3
    SerializationVersion 1.1.0.1

    SystemDirectory : C:WINDOWSsystem32
    BuildNumber : 10586
    Version : 10.0.10586

  13. ggutschi says:

    Hi GCC_CSS,

    I’m expiriencing the same issue since the November update of Windows 10 (Version 1511) on several machines. This is very annoying. We use it in several scripts. Hope there will be a bugfix soon…

    btw: Ed Wilson is awesome and so is his blog 🙂

  14. Chazzz says:

    Hey scripting Guy how can I use this script to deploy to SCCM 2012 clients to create a task schedule to reboot them every Tuesday and Thursday at 6:00 pm local time ???

  15. Avi Z says:

    Thank you very much! love your posts!

  16. Sunny.y says:

    How to schedule the task after 8 days of every second Tuesday?

  17. Hey, Scripting Guy! I am new to PowerShell and am wondering if you can help me with this. I have been tasked with writing a script to grab every Desktop and Laptop from our domain (first two letters of the computer name must match WS or LT), for each of those items, create a scheduled task to reboot at 3AM local time. The syntax I am using to grab the computer names is this:
    # Establish prodclients array + Enumerate all clients with a name starting with “ws” or “lt” and add to array
    [array] $prodclients= @()
    Get-ADComputer -filter * -SearchBase “OU=GenericWorkstationOUName,DC=DOMAIN,DC=com” -Properties “Name” | where {$_.Name -match “ws*” -or “lt*”} | FT DNSHostName | Out-File C:\TEMP\Logoff.txt

    The only problem is that it is grabbing a couple of servers who’s names do not match the criteria. Is there a way to use regular expressions to make sure that the first two characters of the string are exactly WS or LT?

    I understand everything you did in your example, I am just not sure what the arguments are or how to find out what they are. So, I guess I am asking, how do I create a scheduled task to reboot every machine at 3AM local time?

    1. Zack McCloskey says:

      If you haven’t solved this already, try:

      Get-ADComputer -filter * -SearchBase “OU=GenericWorkstationOUName,DC=DOMAIN,DC=com” | where {($_.Name -like “ws*”) -or ($_.Name -like “lt*”)} | FT DNSHostName | Out-File C:\TEMP\Logoff.txt

Skip to main content