A PowerShell logon script Group Policy setting runs a .ps1 file every time a user signs in, and the matching startup setting runs one each time a computer starts. You use them for jobs that no built-in policy covers: writing a per-user configuration file, cleaning up an old application, recording who signed in where, or fixing a setting that preferences cannot reach. This guide covers user logon and logoff scripts, computer startup and shutdown scripts, storage in SYSVOL or NETLOGON, execution policy, timing settings, run-once patterns, a scheduled task alternative, Intune, logging and troubleshooting.
Short answer: Edit a GPO linked to the users’ OU and open User Configuration » Policies » Windows Settings » Scripts (Logon/Logoff) » Logon. On the PowerShell Scripts tab click Show Files…, copy your .ps1 into that folder, click Add… and select it. Set “Configure Logon Script Delay” so the script is not held back, then sign out and in again. For code that needs administrator rights, use a computer startup script instead.
Table of Contents
Which method to use
| Method | Runs as | When | Best for | Watch out for |
|---|---|---|---|---|
| User logon / logoff script | The signed-in user (no elevation) | Each logon or logoff | Per-user files and HKCU changes | Cannot change HKLM or Program Files |
| Computer startup / shutdown script | Local System (computer account on the network) | Each start or shutdown | Machine configuration, installs, cleanup | Runs before logon; network may not be ready |
| GPP Scheduled Task or Immediate Task | SYSTEM or the user | At logon, at a time, or once | Elevated work at logon, delays, retries | More settings to get right |
| Intune platform script | SYSTEM or the user | Once, re-run when changed | Entra joined devices | Not recurring |
| Intune Remediations | SYSTEM or the user | On a schedule | Detect-and-fix jobs | Needs Windows Enterprise or Education licences |
For most tasks we recommend a startup script (machine changes) or a PowerShell logon script Group Policy entry (user changes), and a GPP scheduled task when you need elevation at logon.
Prerequisites
Check these points before you add a PowerShell logon script Group Policy entry:
- Windows 11 Pro, Enterprise or Education, or Windows Server 2016 to 2025, joined to the domain. The PowerShell Scripts tab runs scripts with Windows PowerShell 5.1 (
powershell.exe). - Rights to edit and link GPOs, and GPMC.
- A script you have run manually in the same context: as a standard user for logon scripts, and as SYSTEM for startup scripts (for example with a scheduled task or
psexec -s). - Write access to the script folder restricted to administrators. Anyone who can change the file runs code on every targeted computer.
Method 1: User logon and logoff scripts
This is the classic PowerShell logon script Group Policy setup. The script runs in the user’s session, hidden, with the user’s rights.
- In GPMC, create a GPO linked to the OU that holds the user accounts, for example USR – Logon Script, and edit it.
- Go to
User Configuration » Policies » Windows Settings » Scripts (Logon/Logoff)and double-click Logon. - Open the PowerShell Scripts tab and click Show Files…. Explorer opens the GPO’s own folder,
\\contoso.com\SysVol\contoso.com\Policies\{GPO-GUID}\User\Scripts\Logon. CopySet-UserConfig.ps1into it and close Explorer. - Click Add…, then Browse…, select the file and click Open. Add arguments in Script Parameters if the script takes any, for example
-Site London. - Under For this GPO, run scripts in the following order leave Not configured, or choose Run Windows PowerShell scripts first if the GPO also has batch or VBScript files on the Scripts tab.
- Click OK. The user must sign out and in again;
gpupdatealone does not run a logon script.
Logoff scripts work the same way under Logoff. Keep them short: Windows waits for them before the session ends.
Example logon script
$ErrorActionPreference = 'Stop'
$log = Join-Path $env:LOCALAPPDATA 'Contoso\Logs\logon.log'
New-Item -Path (Split-Path $log) -ItemType Directory -Force | Out-Null
Start-Transcript -Path $log -Append | Out-Null
try {
$key = 'HKCU:\Software\Contoso\LOBApp'
New-Item -Path $key -Force | Out-Null
New-ItemProperty -Path $key -Name 'Server' -Value 'app01.contoso.com' -PropertyType String -Force | Out-Null
Write-Output "Configured for $env:USERNAME on $env:COMPUTERNAME"
}
catch {
Write-Output "Failed: $($_.Exception.Message)"
}
finally {
Stop-Transcript | Out-Null
}
SYSVOL or NETLOGON?
- The GPO’s own folder (Show Files): the script is backed up, copied and deleted with the GPO. This is our default.
- NETLOGON (
\\contoso.com\NETLOGON, which isSYSVOL\contoso.com\scripts): useful when several GPOs share one script. Enter the full UNC path in Add…. Always use the domain name, not a single domain controller, so clients read from their nearest DC. - Another file share: possible, but for startup scripts the computer account needs read access, so grant Domain Computers Read on both the share and NTFS. It also creates a dependency on one server.
Method 2: Computer startup and shutdown scripts
- Create a GPO linked to the computer OU and go to
Computer Configuration » Policies » Windows Settings » Scripts (Startup/Shutdown). - Double-click Startup, open PowerShell Scripts, use Show Files… to copy the script into
…\{GPO-GUID}\Machine\Scripts\Startup, then Add… it. - Restart a test computer.
gpupdate /forcedoes not run it; a restart does.
Startup scripts run as Local System before anyone signs in, so they can write to HKLM and Program Files. On the network they authenticate as the computer account (CONTOSO\PC-0142$). By default Windows waits up to 600 seconds for Group Policy scripts; after that the script is stopped, so long jobs belong in a scheduled task.
Execution policy and signing
The execution policy is set by Computer Configuration » Policies » Administrative Templates » Windows Components » Windows PowerShell » "Turn on Script Execution" (and the same path under User Configuration). Its options map to execution policies: Allow only signed scripts (AllSigned), Allow local scripts and remote signed scripts (RemoteSigned) and Allow all scripts (Unrestricted). A policy set by Group Policy wins over Set-ExecutionPolicy and the -ExecutionPolicy command-line parameter.
- If you enforce AllSigned, sign every GPO script with a code-signing certificate that clients trust:
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Set-AuthenticodeSignature -FilePath .\Set-UserConfig.ps1 -Certificate $cert -TimestampServer 'http://timestamp.digicert.com'
Re-sign after every edit; any change breaks the signature and the script stops running. - If execution policy is not set by Group Policy, a common pattern is to use the Scripts tab instead of the PowerShell tab, with Script Name
powershell.exeand Script Parameters-NoProfile -ExecutionPolicy Bypass -File "\\contoso.com\NETLOGON\Set-UserConfig.ps1". The same pattern withpwsh.exeruns the script under PowerShell 7 if it is installed. - Microsoft is clear that execution policy is not a security boundary. The real control is who can write to the script folder, so check the ACL on SYSVOL and NETLOGON.
Timing settings: delay, synchronous and wait time
The settings that change when a PowerShell logon script Group Policy entry runs are under Administrative Templates » System » Scripts and Administrative Templates » System » Group Policy:
| Setting | Location | Effect |
|---|---|---|
| “Configure Logon Script Delay” | Computer Configuration » … » System » Group Policy | Microsoft introduced a default five-minute delay before logon scripts run in Windows 8.1. Set it to Enabled with 0 minutes, or Disabled, to run them at logon. |
| “Run logon scripts synchronously” | Computer and User Configuration » … » System » Scripts | Explorer (the desktop) waits until logon scripts finish. The computer setting wins over the user setting. |
| “Run startup scripts asynchronously” | Computer Configuration » … » System » Scripts | Startup scripts run at the same time instead of one after another. |
| “Specify maximum wait time for Group Policy scripts” | Computer Configuration » … » System » Scripts | Default 600 seconds; 0 means wait indefinitely. |
| “Run Windows PowerShell scripts first at user logon, logoff” | Computer and User Configuration » … » System » Scripts | PowerShell scripts run before batch and VBScript files in every GPO. |
| “Run Windows PowerShell scripts first at computer startup, shutdown” | Computer Configuration » … » System » Scripts | The same for startup and shutdown. |
| “Always wait for the network at computer startup and logon” | Computer Configuration » … » System » Logon | Makes scripts that need network paths reliable at the first logon. |
Use synchronous processing only when the desktop must not appear before the script is done, for example when the script writes settings the first application reads. It makes every logon slower.
Run-once patterns
Logon scripts run at every logon. For a one-time fix, write a marker and exit early when it exists:
$marker = 'HKCU:\Software\Contoso\LogonTasks'
$name = 'CleanOldShortcuts-v1'
if ((Get-ItemProperty -Path $marker -ErrorAction SilentlyContinue).$name -eq 1) { return }
Remove-Item "$env:USERPROFILE\Desktop\Old App.lnk" -ErrorAction SilentlyContinue
New-Item -Path $marker -Force | Out-Null
New-ItemProperty -Path $marker -Name $name -Value 1 -PropertyType DWord -Force | Out-Null
Change the version suffix in $name when you want the task to run again. For startup scripts use a marker under HKLM:\SOFTWARE\Contoso or a file in $env:ProgramData.
Method 3: Scheduled task through Group Policy Preferences
When code must run elevated at logon, or after a delay, a scheduled task is more reliable than a script entry.
- In a computer GPO go to
Computer Configuration » Preferences » Control Panel Settings » Scheduled Tasks, right-click and choose New » Scheduled Task (At least Windows 7). - On General, set Action to Update, name the task, set the user to
NT AUTHORITY\Systemand tick Run with highest privileges. - On Triggers, add At log on for Any user and, if useful, Delay task for 30 seconds.
- On Actions, add Start a program with
powershell.exeand the arguments-NoProfile -ExecutionPolicy Bypass -File "\\contoso.com\NETLOGON\Fix-Machine.ps1". - On Settings, set Stop the task if it runs longer than to a sensible limit.
For a job that should run once on each computer, choose New » Immediate Task (At least Windows 7) instead, and tick Apply once and do not reapply on the Common tab. An immediate task runs at the next Group Policy refresh without a restart.
Method 4: Intune scripts and Remediations
- Platform scripts: Devices » Scripts and remediations » Platform scripts » Add » Windows 10 and later. Options are Run this script using the logged on credentials, Enforce script signature check and Run script in 64-bit PowerShell host. A script runs once, is retried up to three times on failure, times out after 30 minutes and must be under 200 KB.
- Remediations: a detection script that exits with
1triggers a remediation script, on a schedule (once, hourly or daily). Use this for recurring checks that a logon script used to do. - Logs are in
C:\ProgramData\Microsoft\IntuneManagementExtension\Logs;AgentExecutor.logrecords script runs.
Verify it works
Test every PowerShell logon script Group Policy change with a pilot user and a pilot computer first.
- Confirm the GPO applies:
gpresult /scope user /rfor logon scripts,gpresult /scope computer /rfor startup scripts.gpresult /h C:\Temp\gp.htmllists each script and its parameters under Scripts. - Check the transcript the script writes, for example
%LOCALAPPDATA%\Contoso\Logs\logon.log. A transcript is the quickest way to see what a hidden script did. - Look at the scripts Windows registered for the session:
Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon' -Recurse
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Startup' -Recurse - Open Applications and Services Logs » Microsoft » Windows » GroupPolicy » Operational and filter on the scripts extension to see when script processing ran and whether it reported an error.
- For startup scripts, write the transcript to
C:\ProgramData\Contoso\Logs, because SYSTEM has no user profile folder you can easily read.
Troubleshooting
When a PowerShell logon script Group Policy entry does not run, work through path, context and timing in that order.
| Symptom | Likely cause | Fix |
|---|---|---|
| Script runs minutes after logon | Default logon script delay | Set “Configure Logon Script Delay” to 0 or Disabled |
| Script never runs | GPO linked to the computer OU for a user script, or filtered out | Link user scripts to the user OU (or use loopback); check gpresult |
| Works manually, fails from GPO | Execution policy AllSigned, or file blocked | Sign the script; check “Turn on Script Execution” |
| Startup script cannot read the share | Computer account has no access | Grant Domain Computers Read, or store the script in SYSVOL |
| Access denied writing HKLM from a logon script | Logon scripts run without elevation | Move the task to a startup script or a SYSTEM scheduled task |
| Startup script stops half way | 600-second maximum wait time | Shorten the script or run it as a scheduled task |
| Script fails at first logon only | Network not ready, cached logon | Enable “Always wait for the network at computer startup and logon” |
| PowerShell 7 syntax errors | The PowerShell tab uses Windows PowerShell 5.1 | Call pwsh.exe from the Scripts tab, or keep the script 5.1-compatible |
Roll back or undo
- Remove the script from the PowerShell Scripts tab, or unlink the GPO. The script stops running at the next logon or restart.
- Removing a script does not undo what it changed. If a script set registry values or created files, deploy a short cleanup script (or a GPP item with the Delete action) before you remove it.
- For GPP scheduled tasks, change the item’s action to Delete, let it apply, then delete the item.
- Back up the GPO before changes with
Backup-GPO; the backup includes scripts stored in the GPO folder, but not scripts in NETLOGON.
Keep each PowerShell logon script Group Policy entry small, logged and idempotent, and move anything slow, elevated or recurring to a scheduled task or Intune Remediations.
PowerShell logon script Group Policy at a glance

Official documentation: ADMX_Scripts Policy CSP, about_Execution_Policies, Use PowerShell scripts on Windows devices in Intune.
Related guides: Map Network Drives Group Policy: 2026 Item-Level Targeting Made Easy · Deploy registry settings with Group Policy Preferences · Group Policy loopback processing: merge vs replace for RDS hosts and kiosks.
Frequently asked questions
Why does my Group Policy logon script run several minutes after logon?
Microsoft introduced a default five-minute logon script delay in Windows 8.1. Set “Configure Logon Script Delay” under Computer Configuration, Administrative Templates, System, Group Policy to Enabled with 0 minutes, or to Disabled.
Should I store Group Policy scripts in SYSVOL or NETLOGON?
Store scripts in the GPO’s own folder with Show Files so they are backed up and copied with the GPO. Use NETLOGON when several GPOs share one script, and always reference it through the domain name.
Can a logon script make changes that need administrator rights?
No. Logon scripts run as the signed-in user without elevation. Use a computer startup script or a Group Policy Preferences scheduled task running as SYSTEM for machine-wide changes.
Does -ExecutionPolicy Bypass work when execution policy is set by Group Policy?
No. When “Turn on Script Execution” is configured by Group Policy, it overrides both Set-ExecutionPolicy and the -ExecutionPolicy parameter, so sign the script or change the policy.
How do I make a logon script run only once per user?
Have the script check for a marker value, for example under HKCU:\Software\Contoso, exit if it exists, and write the marker after the work succeeds.