How to Change the Log On Account of a Service in Batch Script
By default, most Windows services run under the "LocalSystem" account. However, for security hardening or to allow a service to access network resources, you often need to change its "Log On" identity to a specific User Account or a Service Account. Managing these identities manually through the services.msc GUI is inefficient for large deployments.
This guide will explain how to use the sc config command to programmatically update the execution account and password for any Windows Service.
The Tool: SC CONFIG OBJ
The sc (Service Control) utility provides the config sub-command, which updates the service's registry configuration. The key parameters for identity management are obj= (for the account name) and password= (for the account password).
Basic Syntax
sc config "ServiceName" obj= "DOMAIN\UserName" password= "MyPassword123"
The Space After Equals.
In all sc commands, you must include a space after the equals sign. Writing obj="DOMAIN\..." will fail. You must write obj= "DOMAIN\...".
Setting Standard System Accounts
Sometimes you want to switch from a custom user back to one of the built-in Windows platform accounts. These accounts do not require a password in the command line.
To Set to LocalService:
sc config "MyService" obj= "NT AUTHORITY\LocalService" password= ""
To Set to NetworkService:
sc config "MyService" obj= "NT AUTHORITY\NetworkService" password= ""
To Set to LocalSystem:
sc config "MyService" obj= "LocalSystem" password= ""
Configuring a Custom Domain or Local User
When using a specific user account, you must provide the full name and the account password.
@echo off
set "svc=MyCustomAgent"
set "user=.\ServiceAppAccount"
:: Verify the service exists
sc query "%svc%" >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Service '%svc%' does not exist.
pause
exit /b 1
)
:: Prompt for the password rather than hardcoding it
set /p "pass=Enter password for %user%: "
echo [ACTION] Updating service log on identity...
sc config "%svc%" obj= "%user%" password= "%pass%"
if %errorlevel% equ 0 (
echo [SUCCESS] Service account updated to: %user%
echo.
echo [IMPORTANT] You must restart the service for the change to take effect:
echo net stop "%svc%" ^&^& net start "%svc%"
) else (
echo [ERROR] Failed to update service configuration.
echo Possible causes:
echo - Script is not running as Administrator.
echo - The account name is incorrect.
echo - The password is wrong.
echo - The account lacks "Log On as a Service" rights.
)
pause
The "Log On as a Service" Permission
Simply changing the account in the sc command is often not enough. For a service to start under a new account, that account must be granted the "Log On as a Service" right in the Windows Local Security Policy.
The sc command does not grant this permission. If you change the account using a script but don't grant the right, the service will fail to start with error: "The service did not start due to a logon failure."
Granting the Right via PowerShell
You can use PowerShell from your Batch script to grant this permission using the secedit tool:
@echo off
set "AccountName=.\ServiceAppAccount"
set "TempDir=%TEMP%\secedit_%RANDOM%"
set "TempDB=%TempDir%\temp.sdb"
set "TempCfg=%TempDir%\temp.cfg"
set "ExportCfg=%TempDir%\export.cfg"
mkdir "%TempDir%"
echo [ACTION] Granting "Log On as a Service" to %AccountName%...
:: Export current security policy
secedit /export /cfg "%ExportCfg%" >nul 2>&1
:: Read current SeServiceLogonRight and append the new account
powershell -NoProfile -Command ^
"$cfg = Get-Content '%ExportCfg%';" ^
"$line = $cfg | Where-Object { $_ -match 'SeServiceLogonRight' };" ^
"if ($line) {" ^
" $newLine = $line + ',%AccountName%';" ^
" $cfg = $cfg -replace [regex]::Escape($line), $newLine" ^
"} else {" ^
" $cfg += 'SeServiceLogonRight = %AccountName%'" ^
"};" ^
"$cfg | Set-Content '%TempCfg%'"
:: Import the updated policy
secedit /configure /db "%TempDB%" /cfg "%TempCfg%" >nul 2>&1
if %errorlevel% equ 0 (
echo [SUCCESS] "Log On as a Service" right granted.
) else (
echo [WARNING] Could not apply the security policy automatically.
echo Grant the right manually via secpol.msc.
)
:: Clean up temporary files
rmdir /s /q "%TempDir%" >nul 2>&1
How to Avoid Common Errors
Wrong Way: Forgetting the quotes around passwords
If your password contains special characters (like &, |, or !), the Batch script might interpret them as commands instead of text.
Correct Way: Wrap the password in double quotes.
password= "P@ssword!"
Problem: Local Account vs. Domain Account
When specifying the obj=, ensure you use the correct format:
- Local Account:
.\AccountNameorComputerName\AccountName - Domain Account:
DOMAIN\AccountName
Best Practice: Restart the Service
Changes to the Log On account do not take effect until the service is restarted.
net stop "%svc%"
timeout /t 3 /nobreak >nul
net start "%svc%"
Best Practices and Security Rules
1. Administrative Privileges
Modifying service credentials requires full Administrator rights. If your script is not elevated, you will get an "Access Denied" error from the sc tool.
2. Password Handling in Scripts
Storing clear-text passwords in a .bat file is a security risk. Prompt for the password at runtime using set /p (as shown in the Custom User section), or use a secure vault system that feeds the variable to the script. Never commit scripts containing passwords to source control.
3. Account Passwords and Expiry
If you set a service to run as a user account, and that user's password expires in 30 days, the service will stop working. For this reason, it is always best to use Managed Service Accounts (MSA) or accounts set to "Password Never Expires."
Conclusions
Updating the "Log On" identity of a service via Batch script is a high-impact operation that streamlines server hardening and setup. While the sc config syntax is simple, the requirement for absolute accuracy in the account name and the strict "space after equals" rule make it a task for careful developers. By automating these changes, you ensure that your services always have the specific permissions they need to operate securely.