Changing Log On Credentials of Windows Services

There was a question from an internal group asking for a way to programmatically
change the log on name (and of course password) of a Windows service – this is the
user account, local or domain, under which the service process runs when started.
Unfortunately, the .NET framework does not provide any class to accomplish this.
You might be tempted to use System.ServiceProcess.ServiceProcessInstaller
class but it allows configuring log on details (via Username and Password properties)
only when installing a new Windows service, not for an already existing one. The
alternatives are WMI and P/Invoke. Here is the sample code:

WMI Version:

using System.Management; // Add reference to System.Management assembly
... ...
// Set SQL Server service to run as NETWORK SERVICE
ManagementObject mo = new ManagementObject("Win32_Service.Name='MSSQLSERVER'");

// 7th parameter is user name and 8th one is password

// Pass null for a parameter if the corresponding property setting shouldn't be changed
mo.InvokeMethod ("Change", new object[] {null, null, null, null, null, null, @"LocalSystem", null, null, null, null});


You can change other settings such as display name, start mode, desktop interactivity, etc as well for a service process. Refer to the documentation of Win32_Service.Change() for more details.

P/Invoke Version:

using System.ServiceProcess;
using System.Runtime.InteropServices;
... ...
[DllImport ("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool ChangeServiceConfig (SafeHandle hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, String lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName);
private const uint SERVICE_NO_CHANGE = 0xffffffff;
... ...
ServiceController sc = new ServiceController ("MSSQLSERVER");
if (ChangeServiceConfig (sc.ServiceHandle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null,
@"NT AUTHORITY\Network Service", null, null))
    Console.WriteLine ("Service configuration changed successfully.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
    Console.WriteLine ("Error changing service configuration. Win32 error code: " + Marshal.GetLastWin32Error().ToString());
sc.Dispose ();

You can find other service configuration settings that can be changed via this Win32 API here.

Couple of Comments: (1) Neither option will work if the calling user does not have the necessary rights to change service configuration details (2) The service should be restarted for the new settings to take effect – what this means is that if the password you supplied for the user name is incorrect, for example, you will not know this until the service is restarted!