guidox / PC

Run a Windows Service Under a Dedicated Account

TL;DR

Create a service account, grant it **Log on as a service**, then set it with **sc config <name> obj= .\svc-app password= ...**. Restart and verify in the service's own log.

Before you start

Requirements

  • Admin rights
  • The service in question
  • 20 minutes
Step by step

Instructions

01

Read the current identity and dependencies

A service that runs as LocalSystem has full local rights. Its account and its dependencies decide what breaks when you change it.

Get-CimInstance Win32_Service -Filter "Name='svcapp'" | Select-Object Name,StartName,State,StartMode
sc.exe qc svcapp
Get-Service svcapp | Select-Object -ExpandProperty DependentServices
02

Create the account

A local account with a long password and no interactive logon is enough for a single machine. The password must not expire silently, or the service fails months later.

$pw = Read-Host -AsSecureString 'Service password'
New-LocalUser -Name 'svc-app' -Password $pw -PasswordNeverExpires -UserMayNotChangePassword -Description 'Service account for svcapp'
Get-LocalUser svc-app | Select-Object Name,Enabled,PasswordLastSet,PasswordExpires
03

Grant log on as a service

Without the right the service fails with error 1069. **secedit** exports the local policy, and the edited file is imported with **/configure**, which is the scriptable way to add the account.

$sid = (New-Object System.Security.Principal.NTAccount('svc-app')).Translate([System.Security.Principal.SecurityIdentifier]).Value
secedit /export /cfg C:\temp\secpol.inf /areas USER_RIGHTS
$cur = (Get-Content C:\temp\secpol.inf | Select-String '^SeServiceLogonRight').Line
(Get-Content C:\temp\secpol.inf) -replace '^SeServiceLogonRight.*', ($cur + ",*$sid") | Set-Content C:\temp\secpol-new.inf
secedit /configure /db C:\temp\secpol.sdb /cfg C:\temp\secpol-new.inf /areas USER_RIGHTS
Select-String -Path C:\temp\secpol.inf -Pattern 'SeServiceLogonRight'
04

Give it only the access it needs

The account needs read access to its program folder and whatever data path it writes. Grant that explicitly instead of adding it to a broad group.

icacls "C:\Program Files\App" /grant "svc-app:(OI)(CI)RX" /T
icacls "D:\AppData" /grant "svc-app:(OI)(CI)M" /T
net localgroup "Users" svc-app /add
Get-LocalGroupMember -Group Users | Select-Object Name
05

Switch the service to the account

**sc config** needs a space after **obj=** and **password=**. The service manager validates the credentials immediately, so a typo fails at once.

sc.exe config svcapp obj= ".\svc-app" password= "P@ssw0rd-from-the-vault"
sc.exe qc svcapp
Restart-Service svcapp -Force
Get-CimInstance Win32_Service -Filter "Name='svcapp'" | Select-Object State,StartName
06

Verify with the service's own log

A service that starts but cannot reach its data logs an access denied. Checking that log is the difference between a running service and a working one.

Get-WinEvent -LogName System -MaxEvents 30 | Where-Object { $_.ProviderName -match 'Service Control Manager' } | Select-Object TimeCreated,Id,Message -First 5
Get-Content 'C:\ProgramData\App\logs\service.log' -Tail 30 -ErrorAction SilentlyContinue
Get-Service svcapp | Select-Object Status,StartType
Troubleshooting

Common issues

The service fails with error 1069

The account lacks Log on as a service, or the password is wrong. Check both before touching the service again.

It starts but cannot read its data

Missing NTFS permission on the data folder. Grant modify rights on that path only, then restart.

It worked until the password expired

Set PasswordNeverExpires on a service account, and store the password somewhere you will find it again.

sc config rejects the command

The spaces around obj= and password= are mandatory. Alternatively use Set-Service -Credential in PowerShell 7.

FAQ

Frequently asked

Is a virtual service account better?

For services that only need local access, yes: gMSA and virtual accounts need no password. Use them when the service supports it.

Can I use a Microsoft account?

Not reliably for a service. A local or domain account is the supported path.

Does this survive a password change?

Only if you update the stored credential with sc config again. That is why service accounts get long, fixed passwords.

How to undo this

Set the service back with sc.exe config svcapp obj= "LocalSystem" password= "", restart it, then remove the account with Remove-LocalUser svc-app and undo the icacls grants.

Changelog · 1 entry
  1. 2026-11-01
    First version
Interactive version: checklist, feedback, related guides →

Free · no account needed · tracks your progress