PS: How To Run As A Scheduled Task

3 minute read

Description:

Many times you will want PS to run as a scheduled task on computers. I have changed this post so many times over the last couple months so here is my final version (works in my env):

To Resolve:

  1. You have two options, run the .ps1 file directly, or, my preferred way with three files per script:

    • For each .ps1 file, I also have a .log and a .bat that goes with it.

    • The .bat is simply the batch file use to call the powershell script. I include “pause” on the end if I am running interactively, or remove it if the script will be a scheduled task.

    • Contents:

    @ECHO OFF
    PowerShell.exe -NoProfile -Command & {Start-Process PowerShell.exe -ArgumentList -NoProfile -ExecutionPolicy Bypass -File “”%~dpn0.ps1″”‘ -Verb RunAs}
    

    NOTE: It is absolutely important that if you use this method, the .bat and the .ps1 need to HAVE THE SAME NAME

    • The .log file is generated by scripts automatically because I prefer to see logging in a file instead of on the console.
  2. Let’s get started – Open the Windows Task Scheduler using whichever method you prefer. Setup the scheduled task:

    • Create a basic task. Click the “Change User or Group” and select SYSTEM. Mark it as “Run whether user is logged in or not” and check the “run with highest privileges”. You can leave the “configure for” as the default (Vista/Server08)

    • Trigger: Set it to run “On A Schedule” – Daily start at 12:05 AM, repeat every 5/10 minutes for a duration of 1 day/indefinitely. Obviously, replace with whatever you want.

    • Action: Start a Program – C:\Scripts\scriptname.bat , start in: C:\Scripts. That’s it!

    • For Powershell you could set it up like:

    • Start a program – Powershell.exe , Add Arguments: .\scriptname.ps1 -NoProfile -ExecutionPolicy Bypass -Verb RunAs , Start in: C:\Scripts\

    • I almost always have problems with this though, hence why I prefer the batch file method.

  3. Once completed, you can check your “scriptname.log” to make sure it is actually running.

The Powershell Way:

  1. Example:

    $taskName = "Chocolatey Daily Upgrade"
    $taskAction = New-ScheduledTaskAction Execute C:\programdata\chocolatey\choco.exe -Argument "upgrade all -y"
    $taskTrigger = New-ScheduledTaskTrigger -At 2am -Daily
    $taskUser = "System"
    Register-ScheduledTask TaskName $taskName -Action $taskAction Trigger $taskTrigger -User $taskUser
    Clear-Host
    
  2. I was going to break this into a new post, but I don’t want people having to search all over the site so here is more notes:

    To Lock Screen Every 5 Minutes Of Inactivity:

    $TaskName = "LockScreen"
    $service = New-Object -ComObject("Schedule.Service")
    $service.Connect()
    $rootFolder = $service.GetFolder("")
    $taskdef = $service.NewTask(0)
    $sets = $taskdef.Settings
    $sets.AllowDemandStart = $true
    $sets.Compatibility = 2
    $sets.Enabled = $true
    $sets.RunOnlyIfIdle = $true
    $sets.IdleSettings.IdleDuration = "PT05M"
    $sets.IdleSettings.WaitTimeout = "PT60M"
    $sets.IdleSettings.StopOnIdleEnd = $true
    $trg = $taskdef.Triggers.Create(6)
    $act = $taskdef.Actions.Create(0)
    $act.Path = "C:\Windows\system32\rundll32.exe"
    $act.Arguments = "user32.dll,LockWorkStation"
    $username = "$env:userdomain" + "\" + "$env:username"
    $user = "$username"
    $rootFolder.RegisterTaskDefinition($TaskName, $taskdef, 6, $user, $null, 3)
    

    PS Scheduled Task To Launch A Batch Script:

    $tName = "RunMyScript"
    $tCommand = "C:\scripts\startup.bat"
    $tAction = New-ScheduledTaskAction -Execute "$tCommand"
    $uName = "$env:userdomain" + "\" + "$env:username"
    $tTrigger = New-ScheduledTaskTrigger -AtLogOn -User $username
    Register-ScheduledTask -Action $tAction -Trigger $tTrigger -TaskName "$tName" -User $uName
    

    PS Scheduled Task To Launch A Powershell Script:

    $tName = "RunMyScript"
    $tCommand = "C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe"
    $tArgs = "-NoProfile -ExecutionPolicy Bypass -File C:\scripts\temp.ps1"
    $tAction = New-ScheduledTaskAction -Execute "$tCommand" -Argument $tArgs
    $uName = "$env:userdomain" + "\" + "$env:username"
    $tTrigger = New-ScheduledTaskTrigger -Daily -At "8:05am"
    Register-ScheduledTask -Action $tAction -Trigger $tTrigger -TaskName "$tName" -User $uName
    

    PS Scheduled Task As System:

    $tName = "RunMyScript"
    $tCommand = "C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe"
    $tArgs = "-NoProfile -ExecutionPolicy Bypass -File C:\_gwill\google\temp\temp.ps1"
    $tAction = New-ScheduledTaskAction -Execute "$tCommand" -Argument $tArgs
    $uName = "NT Authority" + "\" + "System"
    $tTrigger = New-ScheduledTaskTrigger -Daily -At "8:05am"
    Register-ScheduledTask -Action $tAction -Trigger $tTrigger -TaskName "$tName" -User $uName
    

    Using Jobs To Run Specific Commands:

    # NOTE: I like to use commands that output something to a file for these tasks as I'm pretty sure you won't see
    # a powershell window pop up. Haven't tried though!
    # See more about jobs at https://blogs.technet.microsoft.com/heyscriptingguy/2014/05/12/introduction-to-powershell-scheduled-jobs/
    $taskName = "RunScriptblock"
    $scriptBlock = {
    "hello world" | Out-File C:\scripts\test.txt -Append
    "hello world2" | Out-File C:\scripts\test.txt -Append
    "hello world3" | Out-File C:\scripts\test.txt -Append
    }
    $taskTrigger = New-JobTrigger -Daily -At "12:05 AM"
    $taskUser = "domain.com\user"
    Register-ScheduledJob Name $taskName -Credential $taskUser -ScriptBlock $scriptBlock -Trigger $taskTrigger
    # can be viewed at Task Scheduler Library\Microsoft\Windows\Powershell\ScheduledJobs