Community Blogs Published: August 29, 2026 | Updated: August 29, 2026

How to Schedule a PowerShell Script to Run Automatically

Learn how to schedule a PowerShell script using Task Scheduler, macOS launchd, cron, and Azure Automation—so it runs reliably without you clicking a thing.

How to Schedule a PowerShell Script to Run Automatically

If you've ever written a PowerShell script and then had to remember to run it manually every day, every week, or every time something changes — you're doing more work than the script was supposed to save you. The whole point of automation is that it runs without you.

This guide covers every practical way to schedule a PowerShell script to run on its own: on Windows, on macOS, and in the cloud — along with the mistakes that quietly break automation the moment no one's watching it run.

In this guide:

Scheduling on Windows with Task Scheduler Scheduling on macOS with launchd Scheduling on Linux with cron Cloud-based scheduling with Azure Automation (when a script needs to run even if your machine is off) Common pitfalls that break unattended scripts Best practices for reliable automation Why Local Scheduling Isn't Always Enough

Before picking a method, it helps to know what you're optimizing for:

Simple, personal task (backup a folder, clean up logs) → Task Scheduler or launchd is fine Needs to run even if your laptop is off or asleep → cloud-based scheduling (Azure Automation) Runs on a server you control 24/7 → Task Scheduler (Windows Server) or cron (Linux)

Most automation failures don't happen because the script was wrong — they happen because the scheduling didn't account for the environment it's running in. We'll flag those traps as we go.

Method 1: Windows Task Scheduler

Task Scheduler is built into every version of Windows and is the standard way to run PowerShell scripts automatically on a Windows machine or server.

Steps:

Press Win + R, type taskschd.msc, hit Enter In the right panel, click Create Task (not "Basic Task" — Basic Task has fewer options) General tab: Name your task clearly, e.g. Weekly-Report-Automation Select Run whether user is logged on or not — this is the setting most people miss, and skipping it means the task silently fails to run when no one's logged in Triggers tab → New: Set your schedule: Daily, Weekly, or a specific recurrence Actions tab → New: Action: Start a program Program/script: powershell.exe Add arguments: -ExecutionPolicy Bypass -File "C:\Scripts\YourScript.ps1" Click OK, enter your Windows password when prompted (required for "run whether logged on or not")

Common issue: if the task shows "Last Run Result: 0x1" or similar, it's almost always the execution policy or a relative file path issue — always use -ExecutionPolicy Bypass and full absolute paths inside the script, since Task Scheduler doesn't run from the folder your script lives in.

Method 2: macOS — launchd

macOS doesn't use cron by default for user-facing automation anymore; Apple's own scheduler, launchd, is the standard.

Steps:

Find your PowerShell path: which pwsh Create a .plist file at ~/Library/LaunchAgents/com.yourname.scriptname.plist: xml Label com.yourname.scriptname ProgramArguments /opt/homebrew/bin/pwsh -File /Users/you/Scripts/YourScript.ps1 StartCalendarInterval Hour 8 Minute 0 StandardOutPath /Users/you/Scripts/Logs/out.log StandardErrorPath /Users/you/Scripts/Logs/err.log Load it: zsh launchctl load ~/Library/LaunchAgents/com.yourname.scriptname.plist Test it immediately instead of waiting for the schedule: zsh launchctl start com.yourname.scriptname

Important limitation: if the Mac is asleep or shut down at the scheduled time, the run is simply missed. For anything business-critical, this is where cloud scheduling becomes the better choice.

Method 3: Linux — cron

If your script runs on a Linux server, cron is the standard.

bash crontab -e

Add a line — this example runs every Monday at 8 AM:

0 8 * * 1 pwsh -File /home/user/scripts/YourScript.ps1 >> /home/user/scripts/logs/run.log 2>&1

Cron's five fields are: minute, hour, day-of-month, month, day-of-week. Always redirect output to a log file (as shown above) — cron runs silently by default, and a script that fails without logging is a script no one finds out about until it's too late.

Method 4: Cloud Scheduling with Azure Automation

Here's the fully expanded Method 4 — detailed enough that a reader with zero Azure experience can follow it start to finish and end up with a working, scheduled automation. This is written to replace/extend that section in your blog content field.


Method 4: Cloud Scheduling with Azure Automation (Complete Walkthrough)

Local scheduling — Task Scheduler, launchd, cron — has one shared weakness: it depends on a specific machine being powered on. If that laptop is asleep, shut down, or being repaired, the automation silently doesn't run, and often nobody notices for weeks.

Azure Automation solves this by running your script on Microsoft's own servers, on a schedule, completely independent of any personal computer. This walkthrough covers everything: generating a certificate, registering an app, setting up the automation environment, and scheduling it — using a real PowerShell script as the working example.

What you'll need before starting:

  • Access to portal.azure.com with permission to create resources (an Azure/Microsoft 365 admin)
  • A Mac or Windows machine with a terminal, just for the one-time certificate generation
  • The PowerShell script you want to automate

Step 1: Generate a Certificate

Cloud automation can't answer an interactive login prompt — there's no one there to click "Yes" or paste a device code. So instead of a username/password login, we use a certificate: a file-based credential the automation can use to authenticate on its own, silently, every time it runs.

On a Mac, open Terminal and run:

mkdir -p ~/Desktop/AutomationSetup cd ~/Desktop/AutomationSetup openssl req -x509 -newkey rsa:2048 -keyout AutomationKey.pem -out AutomationCert.pem -days 730 -nodes -subj "/CN=MyAutomation" openssl pkcs12 -export -out AutomationCert.pfx -inkey AutomationKey.pem -in AutomationCert.pem -passout pass:ChooseAStrongPassword openssl x509 -in AutomationCert.pem -noout -fingerprint -sha1 base64 -i AutomationCert.pfx | pbcopy

This creates a certificate valid for two years. The last command copies a long base64 text string to your clipboard — you'll paste this into an Azure Variable in Step 6, so don't close this terminal window yet.

The fingerprint command prints something like SHA1 Fingerprint=A1:B2:C3:... — copy everything after the = and remove the colons. Save this thumbprint somewhere; you may need it depending on your authentication method.


Step 2: Register an App in Azure (Entra ID)

This "app" is the automation's identity — the thing Azure checks permissions against.

  1. Go to portal.azure.com → search Microsoft Entra ID → open it
  2. Left menu → App registrations+ New registration
  3. Name it something identifiable, e.g. MyScriptAutomation
  4. Leave account type on the default (single tenant)
  5. Click Register
  6. Copy and save two values shown on the page: Application (client) ID and Directory (tenant) ID

Attach the certificate:

  1. Left menu → Certificates & secretsCertificates tab → Upload certificate
  2. Select the .pem file (not the .pfx) from Step 1 → Add

Grant the permissions your script actually needs (this example assumes SharePoint access, but the pattern is the same for any Microsoft Graph/Azure resource your script touches):

  1. Left menu → API permissions+ Add a permission
  2. Choose the relevant API (e.g. SharePoint, Microsoft Graph)
  3. Select Application permissions (not Delegated — delegated permissions need a signed-in user, which won't exist in an unattended run)
  4. Check the specific permission your script needs (e.g. Sites.FullControl.All for full SharePoint access)
  5. Click Add permissions
  6. Click Grant admin consent for [your organization] → confirm

Double-check the permission row now shows a green checkmark and "Granted" — if it doesn't, whoever clicked consent needs to be a Global Administrator or equivalent.


Step 3: Create the Automation Account

  1. Portal search bar → Automation Accounts+ Create
  2. Create a new resource group (or use an existing one)
  3. Give the account a name, pick a region close to you
  4. Review + createCreate, then wait for deployment

Step 4: Create a Runtime Environment

This defines exactly which PowerShell version and modules your script runs with — getting this right up front avoids a whole category of version-mismatch errors later.

  1. Inside the Automation Account, look for "Try Runtime Environment Experience" near the top and click it (this enables the newer, more reliable module-management interface)
  2. Left menu → Runtime Environments+ Create
  3. Choose PowerShell, version 7.4 (7.4 has the broadest module compatibility as of this writing)
  4. Name it, e.g. PS74-MyModules, then Create
  5. Open it → Add from gallery → search for whatever module your script depends on (for example, PnP.PowerShell for SharePoint automation) → Add
  6. Wait for its status to show Available — this can take 10–20 minutes, which is normal

Step 5: Store Configuration as Variables

Never hard-code secrets directly into a script that lives in the cloud. Instead, store them as Automation Variables, and have the script read them at runtime.

Left menu → Variables+ Add a variable, for each value your script needs. At minimum, for certificate-based auth:

  • TenantId — your Directory (tenant) ID from Step 2
  • ClientId — your Application (client) ID from Step 2
  • CertBase64 — paste from your clipboard (Step 1) — check "Encrypted"
  • CertPassword — the password you set in Step 1 — check "Encrypted"

Add whatever else your specific script needs — site URLs, folder names, thresholds, anything that would otherwise be hard-coded.


Step 6: Create the Runbook

The Runbook is where your actual script lives and runs.

  1. Left menu → Runbooks+ Create a runbook
  2. Name it clearly
  3. Runbook type: PowerShell
  4. Runtime Environment: select the one you created in Step 4 — this has to be chosen now, at creation time; it generally can't be changed on an existing runbook afterward
  5. Create

You'll land in a code editor. Before pasting your script in, three adaptations are usually needed to make a script that ran on your own machine work correctly in Azure's cloud sandbox:

Read config from Variables, not a local file. A script that read Config.json from disk needs to instead call:

$TenantId = Get-AutomationVariable -Name 'TenantId'

for each value, since the cloud sandbox has no persistent local files between runs.

Authenticate with the certificate directly, not a local cert store. Instead of a certificate thumbprint pointing at your machine's Keychain or Certificate Store, use:

Connect-PnPOnline -Url $Url -ClientId $ClientId -Tenant $TenantId -CertificateBase64Encoded $CertBase64 -CertificatePassword $SecurePassword

Log with Write-Host, not Write-Output, inside any function that also returns a value. This one is subtle but important: in PowerShell, anything a function writes with Write-Output becomes part of that function's actual return value when captured with $x = Some-Function. If a function both logs a status message and returns something useful (like a connection object), using Write-Output for the log line will silently corrupt the return value into a multi-item array — producing a confusing error like: Cannot convert 'System.Object[]' to the type '...' required by parameter 'Connection'. Using Write-Host for all logging avoids this entirely, since it writes to a separate stream that never gets captured by variable assignment, while still showing up in the Runbook's Output logs.

Paste your adapted script into the editor, then:

  1. Save
  2. Publish → confirm

Step 7: Test It Once

  1. On the runbook's Overview page, click Start
  2. Click into the job that appears
  3. Check the Output tab for your script's log messages
  4. Check the Exception tab for any errors

If something fails, the exact error message is your best clue — search it verbatim; most Azure Automation errors are common enough that others have hit and solved them too.


Step 8: Schedule It

  1. On the runbook's page, left menu → Schedules+ Add a scheduleCreate a new schedule
  2. Name it, set a start date/time, and your timezone
  3. Recurrence: Recurring → set the interval (e.g. every 1 week, on Monday)
  4. Create
  5. Confirm the Parameters and run settings step (default settings are fine unless your script takes parameters)

From this point forward, Azure runs your script automatically, on schedule, whether any computer is on or not — the entire point of moving automation to the cloud.


Troubleshooting: Errors You Might Actually Hit

A few Azure Automation-specific issues are common enough to call out by their exact error text, since that's usually what people search for:

  • "Cannot bind argument to parameter 'Path' because it is an empty string." — Azure's sandbox starts with no working directory set. Add Set-Location -Path $env:TEMP at the very top of your script, before any module calls.
  • "The module ... requires a minimum PowerShell version of '7.4.0' to run." — the module version imported doesn't match your Runbook's PowerShell version. Make sure your Runtime Environment and the module you added to it both target the same PowerShell version.
  • "A parameter cannot be found that matches parameter name 'Connection'." — not every cmdlet in every module accepts a -Connection parameter the way you'd expect; check the specific cmdlet's actual supported parameters rather than assuming consistency across a module.
  • "Cannot convert 'System.Object[]' to the type '...' required by parameter." — as covered in Step 6, this is almost always a function logging with Write-Output before returning its real value. Switch logging calls to Write-Host.

Need This Set Up for Your Organization?

Reading through this walkthrough is one thing — actually getting a certificate generated, an app registered with the right permissions, a Runtime Environment configured with the correct module versions, and a script adapted to run cleanly in Azure's sandbox is a different matter. Small mismatches at any single step — a wrong PowerShell version, a missed admin consent, a logging pattern that silently corrupts a return value — are enough to stall the whole thing, and debugging cloud automation blind is nobody's idea of a good afternoon.

At Zyppro, this is exactly the kind of work we handle for clients directly — from scripting the automation itself to standing up the full Azure Automation pipeline around it: certificate-based authentication, scheduled Runbooks, monitoring, and the adaptations that make a script built for a local machine actually reliable when it's running unattended in the cloud.

If you'd rather have this running correctly the first time than spend a weekend chasing cryptic Azure error messages, get in touch with us — we'll take it from your script (or your requirements) straight through to a scheduled, working automation.