
Run Scheduled Tasks as SYSTEM With Highest Privileges
Before you run this
This guide creates a Windows scheduled task that runs a script non-interactively under NT AUTHORITY\SYSTEM with Run with highest privileges enabled. That combination gives the task the full rights of the local machine account and an unfiltered admin token — it is the most powerful context a local task can run in. Use it only for jobs that genuinely need it (patching, service restarts, disk maintenance), and keep the script it runs small and trusted, because anything that task does, it does with no guardrails.
- Elevation required. Creating a SYSTEM task, or any task with
-RunLevel Highest, requires an elevated (Run as administrator) PowerShell or command prompt. A normal user session cannot register a task that runs as SYSTEM. The built-inScheduledTasksmodule ships with Windows 8 / Server 2012 and later, so there is nothing to install on Server 2022. - Test first. Read the script your task will call before you wire it up, and register the task on a test VM or a non-production box first. Run it once manually and confirm the outcome before you trust it on a schedule on a live server.
- What it changes. Registering a task writes a new entry to the Task Scheduler Library. That is reversible — you delete the task with
Unregister-ScheduledTask(shown at the end). What is not reversible is whatever your script does when it fires as SYSTEM. A destructive script run as SYSTEM has nothing stopping it, so treat the payload with the caution its privilege deserves. - SYSTEM has no network identity of its own. As SYSTEM the task authenticates to remote resources as the computer account (
DOMAIN\MACHINE$), not as a user. Mapped drives, user profile paths, and credentials stored per-user are not available. If your script needs a specific user's credentials or a UNC share the machine account can't reach, SYSTEM is the wrong principal — use a dedicated service account instead.
I'm assuming Windows Server 2022, an elevated PowerShell 5.1 session, and a script already saved on disk that you want to schedule.
The two supported ways
There are two mainstream, well-established tools for this: the ScheduledTasks PowerShell module (Register-ScheduledTask and friends) and the classic schtasks.exe. I'll use PowerShell as the primary path because it's clearer and scriptable, and show the schtasks.exe equivalent for anyone who prefers it.
The GUI (Task Scheduler → Create Task) can do the "highest privileges" part with its Run with highest privileges checkbox, but the GUI's Change User or Group dialog is the fiddly place to enter SYSTEM. For SYSTEM specifically, the command line is the cleaner route.
Create the task in PowerShell
Save your script somewhere sensible — I'll use C:\Scripts\maintenance.ps1 as the placeholder; replace it with your real path. Then build the task from four objects: an action, a trigger, a principal, and (optionally) settings.
# Run in an ELEVATED PowerShell session.
# What the task runs. Adjust the path and arguments to your script.
$action = New-ScheduledTaskAction `
-Execute "powershell.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"C:\Scripts\maintenance.ps1`""
# When it runs. Daily at 02:00 here — change to suit.
$trigger = New-ScheduledTaskTrigger -Daily -At 2:00AM
# WHO it runs as: SYSTEM, non-interactive, with the highest (unfiltered) token.
$principal = New-ScheduledTaskPrincipal `
-UserId "SYSTEM" `
-LogonType ServiceAccount `
-RunLevel Highest
# Optional but sensible: let it run even on battery, and start if a scheduled run was missed.
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-StartWhenAvailable
# Register it under an obvious name. Replace the name to suit your naming convention.
Register-ScheduledTask `
-TaskName "Nightly Maintenance" `
-Action $action `
-Trigger $trigger `
-Principal $principal `
-Settings $settings `
-Description "Runs maintenance.ps1 as SYSTEM with highest privileges."
A few things worth knowing:
-UserId "SYSTEM"is the short form Windows accepts forNT AUTHORITY\SYSTEM.-LogonType ServiceAccountis the correct logon type for the built-in service accounts (SYSTEM, LOCAL SERVICE, NETWORK SERVICE) and needs no password.-RunLevel Highestis the exact equivalent of the GUI's Run with highest privileges checkbox. For SYSTEM this is somewhat academic — SYSTEM is already fully privileged — but it's the correct flag and matters if you ever switch the principal to an admin user.-ExecutionPolicy Bypasson thepowershell.execall keeps the script from being blocked by machine execution policy without changing policy globally. If your environment forbids this, sign your script instead.
The schtasks.exe equivalent
If you'd rather use the classic tool, this creates the same task. Run it from an elevated command prompt:
schtasks /Create ^
/TN "Nightly Maintenance" ^
/TR "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"C:\Scripts\maintenance.ps1\"" ^
/SC DAILY /ST 02:00 ^
/RU "SYSTEM" ^
/RL HIGHEST
Here /RU "SYSTEM" sets the run-as account (no /RP password needed for SYSTEM), and /RL HIGHEST is the highest-privileges level. This is a well-documented tool; for the full flag list see Microsoft Learn's schtasks reference.
Verify it worked
First, confirm the task exists and check how it's configured:
Get-ScheduledTask -TaskName "Nightly Maintenance" |
Select-Object TaskName, State,
@{n='RunAs'; e={$_.Principal.UserId}},
@{n='RunLevel';e={$_.Principal.RunLevel}}
You want to see RunAs = SYSTEM and RunLevel = Highest.
Now run it once on demand rather than waiting for the schedule, and check the result:
Start-ScheduledTask -TaskName "Nightly Maintenance"
# Wait a moment for it to finish, then inspect the outcome.
Get-ScheduledTaskInfo -TaskName "Nightly Maintenance" |
Select-Object LastRunTime, LastTaskResult, NextRunTime
LastTaskResult of 0 means the task exited successfully. Non-zero values are exit codes from what the task ran — chase those in your script, not the scheduler. You can also open Task Scheduler (taskschd.msc), find the task in the Library, and read the History tab and the Last Run Result column for the same information in the GUI.
Because SYSTEM runs with no interactive desktop, don't expect to see anything on screen. Have your script write to a log file or the Windows Event Log so you have proof it ran and did what you expected.
Undo / roll back
Removing the task is a single command in the elevated session:
Unregister-ScheduledTask -TaskName "Nightly Maintenance" -Confirm:$false
Or with the classic tool:
schtasks /Delete /TN "Nightly Maintenance" /F
Deleting the task removes only the schedule entry — it does not undo anything the task already did on previous runs. If your script made changes you need to reverse, that's a separate job.
When SYSTEM is the wrong answer
If the task needs to reach a specific network share, use domain credentials, or touch a user's profile, don't reach for SYSTEM. Create a dedicated (ideally a Group Managed Service Account) and register the task under that principal instead — the New-ScheduledTaskPrincipal step is where you'd swap the identity. SYSTEM is for local, machine-scoped work; keep it in that lane.
Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.
More about the author →Was this article helpful?
Tap a star — no sign-in needed.
Be the first to rate this article.
Related guides
Automate Print-Queue Cleanup and Clearing Stuck Jobs
Stuck print jobs are one of those recurring, low-glamour tickets: a queue jams, one document sits in "Error" or "Deleting" forever, and everything behind it stalls. This guide gives you two standard tools — a graceful per-job cleanup and the classic spooler reset — and shows how to run them safely on a schedule.
Schedule a Nightly SQL Server Backup with a PowerShell Job
This guide sets up an unattended nightly full database backup . A short PowerShell script calls Backup-SqlDatabase to write a .bak file to a folder, and Windows Task Scheduler runs that script on a schedule under a service account.
Automate a Scheduled Folder Backup with Robocopy and Task Scheduler
This guide sets up a nightly copy of one folder to a backup location using robocopy driven by a script, then schedules that script to run unattended with Windows Task Scheduler. The point is a low-fuss, repeatable file copy — not a full backup product with versioning or bare-metal restore.
Detect and Quarantine Suspicious File Extensions in Shared Folders
This guide builds a PowerShell script that scans an SMB shared folder for files whose extensions are commonly used to carry malware ( .exe , .scr , .js , .vbs , .bat , and so on), and moves any it finds into a locked-down quarantine folder outside the share, writing every action to a log. It is a crude, extension-based screen — a tripwire, not an antivirus engine. It does not inspect file contents and will not catch a malicious .docm or a renamed payload. Treat it as one layer, not the layer.




