Does anyone have a Powershell script to change the credentials used by a Windows service?
-
Can you remove the bonus question text? I notice you posted that separately. Let's not confuse people and have the answers go to the wrong place. – halr9000 Nov 24 '08 at 13:35
-
1[Using `sc.exe`](http://stackoverflow.com/q/308298/1394393) is also an option. – jpmc26 Apr 13 '17 at 21:03
11 Answers
Bit easier - use WMI.
$service = gwmi win32_service -computer [computername] -filter "name='whatever'"
$service.change($null,$null,$null,$null,$null,$null,$null,"P@ssw0rd")
Change the service name appropriately in the filter; set the remote computer name appropriately.
-
28Just a note on this answer. If you want to update the user account, you need to be update the value preceding password. i.e. $service.change($null,$null,$null,$null,$null,$null,".\MyAccount","P@ssw0rd"). It seems you always need to prefix the account name with the domain name or ".\" otherwise it won't work. For more information regarding the other parameters please see here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384901(v=vs.85).aspx – Rohland Jun 19 '12 at 10:25
-
Also, take a look at my answer below before using this. Service account changes require a service reset to take effect and sample code is included. – Chris N Sep 12 '12 at 15:59
-
7Note that if you are specifying an account other than Local System as per @Rohland's comment above, you must also specify $false for parameter 6 ("DesktopInteract"). Only the Local System account can be granted permissions to interact with the desktop. – alastairs Jan 17 '13 at 14:38
-
-
-
3I had a lot of trouble with this approach... lots of assorted failures. I ended up finding that invoking sc was a lot more reliable: `& sc.exe config "$servicename" obj= "[$domain\$username]" password= "[$password]"` -- reference: http://stackoverflow.com/questions/308298/ – Jude Allred Feb 03 '14 at 19:41
-
1Instead of filtering on name, you can filter on DisplayName, might alleviate issues where there is a '$' in the name. – Nick DeMayo Mar 07 '14 at 18:52
-
1For anyone interested in the signature of that change() method of the Win32_Service class look here: http://msdn.microsoft.com/en-us/library/aa384901(v=vs.85).aspx – J T R May 14 '14 at 19:48
-
If I need access to ComputerName using a username and password, not the same that windows service credential ? – Kiquenet Oct 16 '14 at 21:16
-
not working. nor the sc in Windows 2019 data center. If it is manually changed to the user and then run, it works (but that is not what I wanted) – Blue Clouds Jun 19 '20 at 19:17
I wrote a function for PowerShell that changes the username, password, and restarts a service on a remote computer (you can use localhost if you want to change the local server). I've used this for monthly service account password resets on hundreds of servers.
You can find a copy of the original at http://www.send4help.net/change-remote-windows-service-credentials-password-powershel-495
It also waits until the service is fully stopped to try to start it again, unlike one of the other answers.
Function Set-ServiceAcctCreds([string]$strCompName,[string]$strServiceName,[string]$newAcct,[string]$newPass){
$filter = 'Name=' + "'" + $strServiceName + "'" + ''
$service = Get-WMIObject -ComputerName $strCompName -namespace "root\cimv2" -class Win32_Service -Filter $filter
$service.Change($null,$null,$null,$null,$null,$null,$newAcct,$newPass)
$service.StopService()
while ($service.Started){
sleep 2
$service = Get-WMIObject -ComputerName $strCompName -namespace "root\cimv2" -class Win32_Service -Filter $filter
}
$service.StartService()
}

- 7,239
- 1
- 24
- 27
-
1Great +1. You should edit and include usage line. Usage: Set-ServiceAcctCreds -strCompName "Computer1" -strServiceName "Service" -newAcct "DOM\ServiceUser" -newPass 'newSecureWord' – DGaleano Feb 10 '16 at 14:42
The PowerShell 6 version of Set-Service
now has the -Credential
parameter.
Here is an example:
$creds = Get-Credential
Set-Service -DisplayName "Remote Registry" -Credential $creds
At this point, it is only available via download via GitHub.
Enjoy!

- 2,173
- 1
- 29
- 43
I created a text file "changeserviceaccount.ps1" containing the following script:
$account="domain\user"
$password="passsword"
$service="name='servicename'"
$svc=gwmi win32_service -filter $service
$svc.StopService()
$svc.change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
$svc.StartService()
I used this as part of by post-build command line during the development of a windows service:
Visual Studio: Project properties\Build Events
Pre-build event command line:
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe" myservice.exe /u
Post-build event command line:
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe" myservice.exe
powershell -command - < c:\psscripts\changeserviceaccount.ps1

- 3,574
- 6
- 39
- 45
A slight variation on the other scripts here, is below. This one will set credentials for any/all services running under a given login account. It will only attempt to restart the service if it was already running, so that we don't accidentally start a service that was stopped for a reason. The script has to be run from and elevated shell (if the script starts telling you about ReturnValue = 2
, you're probably running it un-elevated). Some usage examples are:
all services running as the currently logged in user, on the local host:
.\set-servicecredentials.ps1 -password p@ssw0rd
all services running as user:
somedomain\someuser
on hostsomehost.somedomain
:.\set-servicecredentials.ps1 somehost.somedomain somedomain\someuser p@ssw0rd
Set-ServiceCredentials.ps1:
param (
[alias('computer', 'c')]
[string] $computerName = $env:COMPUTERNAME,
[alias('username', 'u')]
[string] $serviceUsername = "$env:USERDOMAIN\$env:USERNAME",
[alias('password', 'p')]
[parameter(mandatory=$true)]
[string] $servicePassword
)
Invoke-Command -ComputerName $computerName -Script {
param(
[string] $computerName,
[string] $serviceUsername,
[string] $servicePassword
)
Get-WmiObject -ComputerName $computerName -Namespace root\cimv2 -Class Win32_Service | Where-Object { $_.StartName -eq $serviceUsername } | ForEach-Object {
Write-Host ("Setting credentials for service: {0} (username: {1}), on host: {2}." -f $_.Name, $serviceUsername, $computerName)
$change = $_.Change($null, $null, $null, $null, $null, $null, $serviceUsername, $servicePassword).ReturnValue
if ($change -eq 0) {
Write-Host ("Service Change() request accepted.")
if ($_.Started) {
$serviceName = $_.Name
Write-Host ("Restarting service: {0}, on host: {1}, to implement credential change." -f $serviceName, $computerName)
$stop = ($_.StopService()).ReturnValue
if ($stop -eq 0) {
Write-Host -NoNewline ("StopService() request accepted. Awaiting 'stopped' status.")
while ((Get-WmiObject -ComputerName $computerName -Namespace root\cimv2 -Class Win32_Service -Filter "Name='$serviceName'").Started) {
Start-Sleep -s 2
Write-Host -NoNewline "."
}
Write-Host "."
$start = $_.StartService().ReturnValue
if ($start -eq 0) {
Write-Host ("StartService() request accepted.")
} else {
Write-Host ("Failed to start service. ReturnValue was '{0}'. See: http://msdn.microsoft.com/en-us/library/aa393660(v=vs.85).aspx" -f $start) -ForegroundColor "red"
}
} else {
Write-Host ("Failed to stop service. ReturnValue was '{0}'. See: http://msdn.microsoft.com/en-us/library/aa393673(v=vs.85).aspx" -f $stop) -ForegroundColor "red"
}
}
} else {
Write-Host ("Failed to change service credentials. ReturnValue was '{0}'. See: http://msdn.microsoft.com/en-us/library/aa384901(v=vs.85).aspx" -f $change) -ForegroundColor "red"
}
}
} -Credential "$env:USERDOMAIN\$env:USERNAME" -ArgumentList $computerName, $serviceUsername, $servicePassword

- 31,451
- 23
- 97
- 126
-
1@Kiquenet I've modified the script for you to prompt for credentials to the remote host. – grenade Oct 17 '14 at 10:44
Just making @alastairs's comment more visible: the 6th parameter must be $false
instead of $null
when you use domain accounts:
$service = Get-WMIObject -class Win32_Service -filter "name='serviceName'"
$service.change($null, $null, $null, $null, $null, $false, "DOMAIN\account", "mypassword")
Without that it was working for 4/5 of the services I tried to change, but some refused to be changed (error 21).

- 1,707
- 17
- 24
Considering that whithin this class:
$class=[WMICLASS]'\\.\root\Microsoft\SqlServer\ComputerManagement:SqlService'
there's a method named setserviceaccount()
, may be this script will do what you want:
# Copyright Buck Woody, 2007
# All scripts provided AS-IS. No functionality is guaranteed in any way.
# Change Service Account name and password using PowerShell and WMI
$class = Get-WmiObject -computername "SQLVM03-QF59YPW" -namespace
root\Microsoft\SqlServer\ComputerManagement -class SqlService
#This remmed out part shows the services - I'll just go after number 6 (SQL
#Server Agent in my case):
# foreach ($classname in $class) {write-host $classname.DisplayName}
# $class[6].DisplayName
stop-service -displayName $class[6].DisplayName
# Note: I recommend you make these parameters, so that you don't store
# passwords. At your own risk here!
$class[6].SetServiceAccount("account", "password")
start-service -displayName $class[6].DisplayName

- 1,262,500
- 529
- 4,410
- 5,250
$svc = Get-WmiObject win32_service -filter "name='serviceName'"
the position of username and password can change so try this line to find the right place$svc.GetMethodParameters("change")
$svc.change($null,$null,$null,$null,$null,$null,$null,$null,$null,"admin-username","admin-password")

- 7,295
- 4
- 71
- 112
What I cannot find in the default PS stack, I find it implemented in Carbon
:
http://get-carbon.org/help/Install-Service.html
http://get-carbon.org/help/Carbon_Service.html (Carbon 2.0 only)

- 2,847
- 1
- 26
- 21
The given answers do the job.
Although, there is another important detail; in order to change the credentials and run the service successfully, you first have to grant that user account permissions to 'Log on as a Service'.
To grant that privilege to a user, use the Powershell script provided here by just providing the username of the account and then run the other commands to update the credentials for a service as mentioned in the other answers, i.e.,
$svc=gwmi win32_service -filter 'Service Name'
$svc.change($null,$null,$null,$null,$null,$null,'.\username','password',$null,$null,$null)

- 2,576
- 4
- 29
- 36
-
1error gwmi : Invalid query "select * from win32_service where myservice" – Blue Clouds Jun 19 '20 at 19:15
Sc config example. First allowing modify access to a certain target folder, then using the locked down "local service" account. I would use set-service -credential, if I had PS 6 or above everywhere.
icacls c:\users\myuser\appdata\roaming\fahclient /grant "local service:(OI)(CI)(M)"
sc config "FAHClient" obj="NT AUTHORITY\LocalService"

- 23,033
- 6
- 64
- 66