(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisbon

How to Schedule a PowerShell Script in Task Scheduler

João Barros 14 de July de 2026 5 min read

Scheduling a PowerShell script in Task Scheduler is the simplest way to make a routine run on its own: export a CSV every morning, clean up logs on Sundays, or call an API every hour. No extra infrastructure is needed — Task Scheduler already ships with Windows. What follows is the full walkthrough, including the classic error that makes the task look like it ran while producing nothing.

Prerequisites

  • Windows 10/11 or Windows Server, with Task Scheduler.
  • A .ps1 script you have already tested by hand in the console.
  • Administrator permissions (required for tasks that run without a logged-on session).
  • Windows PowerShell 5.1 (powershell.exe) or PowerShell 7 (pwsh.exe).

Step 1: Prepare the script to run unattended

A script that works in your console can fail silently once it is scheduled: it runs from a different working directory, with no profile loaded and nobody around to answer prompts. Two rules will save you hours of debugging — always use absolute paths, and write a log.

# C:\Scripts\ExportarVendas.ps1
$ErrorActionPreference = 'Stop'
$log = 'C:\Scripts\logs\exportar-vendas.log'
New-Item -ItemType Directory -Path (Split-Path $log) -Force | Out-Null

try {
    "$(Get-Date -Format s) - inicio" | Add-Content $log

    $dados = Import-Csv 'C:\Dados\vendas.csv'
    $dados | Where-Object { [decimal]$_.Total -gt 100 } |
        Export-Csv 'C:\Dados\vendas_top.csv' -NoTypeInformation -Encoding UTF8

    "$(Get-Date -Format s) - OK ($($dados.Count) linhas)" | Add-Content $log
    exit 0
}
catch {
    "$(Get-Date -Format s) - ERRO: $($_.Exception.Message)" | Add-Content $log
    exit 1
}

Note the exit 0 and exit 1: that is how the script reports success or failure to Task Scheduler, which surfaces them in the Last Run Result column.

Step 2: Create the task in the GUI

Open Task Scheduler (taskschd.msc) and pick Create Task — not Create Basic Task, because the latter does not expose the options that matter here.

  1. General: name the task, then tick Run whether user is logged on or not and Run with highest privileges.
  2. Triggers → New → Daily, at 07:00.
  3. Actions → New → Start a program:
    • Program/script: powershell.exe
    • Add arguments: -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\ExportarVendas.ps1"
    • Start in: C:\Scripts
The path to the .ps1 always goes inside -File and in quotes. If you put it directly in the Program/script field, Windows will try to open it in an editor instead of running it.

Step 3: Create the same task with PowerShell

If you need to repeat this on ten servers, do it in code. The ScheduledTasks module is already installed on Windows.

$acao = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\ExportarVendas.ps1"' -WorkingDirectory 'C:\Scripts'

$gatilho = New-ScheduledTaskTrigger -Daily -At 07:00

$definicoes = New-ScheduledTaskSettingsSet -StartWhenAvailable -MultipleInstances IgnoreNew -ExecutionTimeLimit (New-TimeSpan -Hours 1)

$params = @{
    TaskName = 'Exportar Vendas'
    TaskPath = '\bConcepts\'
    Action   = $acao
    Trigger  = $gatilho
    Settings = $definicoes
    User     = 'SYSTEM'
    RunLevel = 'Highest'
    Force    = $true
}

Register-ScheduledTask @params

The SYSTEM account always runs, with no password and no logged-on session — ideal when the script only touches local files. If you need to reach a network share or a database using integrated authentication, register the task with a domain service account (-User 'DOMINIO\svc_dados' -Password '...') and grant it permissions on those resources.

For PowerShell 7, swap the executable for 'C:\Program Files\PowerShell\7\pwsh.exe'; the arguments stay the same.

Step 4: Avoid the Execution Policy error

This is the most commonly reported error: the task finishes in seconds, the log stays empty, and Event Viewer shows File cannot be loaded because running scripts is disabled on this system. The cause is the machine's Execution Policy.

The -ExecutionPolicy Bypass parameter fixes it for that process only — it does not change the computer's policy or weaken global security. -NoProfile, in turn, prevents the user profile (which may not even exist for a service account) from loading and changing variables or the current folder.

Step 5: Test without waiting for the schedule

Do not wait until 07:00 to find out whether it works. Force an immediate run:

Start-ScheduledTask -TaskName 'Exportar Vendas' -TaskPath '\bConcepts\'

Verify the result

Check the three usual signals — the exit code, the script log, and the file produced:

Get-ScheduledTaskInfo -TaskName 'Exportar Vendas' -TaskPath '\bConcepts\' |
    Select-Object LastRunTime, LastTaskResult, NextRunTime

Get-Content 'C:\Scripts\logs\exportar-vendas.log' -Tail 5

How to read LastTaskResult:

  • 0 — success (the script returned exit 0).
  • 1 — the script caught an error and returned exit 1: check the log.
  • 0x41301 — the task is still running.
  • 0x41303 — the task has never run.

If you need more detail, the scheduler's own history lives in the Microsoft-Windows-TaskScheduler/Operational event log.

Conclusion

With a well-prepared script (absolute paths, a log, and exit codes) and a task registered in code, you get automation that is reliable and reproducible on any Windows server. The natural next step is to parameterise the script, send an email whenever LastTaskResult is non-zero, and — once the routine has to run outside the local network — move it to an Azure Automation Runbook. One last tip: if the task runs on your laptop, tick Wake the computer to run this task — what good is a schedule if the machine was asleep?