How do I programmatically set the "Log On" credentials for an arbitrary Windows service using c# (wmi/interop is fine)?
Note, my program is running as an administrator and I need the change to persist (for all subsequent service restarts)
Ideally the method has the following sig:
void SetWindowsServiceCreds(string serviceName, string username, string password)
{
// TODO write me
}
In the right pane, right-click ‘Log on as a service’ and select properties. Click on the ‘Add User or Group…’ button to add the new user. In the ‘Select Users or Groups’ dialogue, find the user you wish to enter and click ‘OK’ Click ‘OK’ in the ‘Log on as a service Properties’ to save changes. Then try again with the added user.
Expand Local Policy and click User Rights Assignment. In the right pane, right-click Log on as a service and select Properties. Click Add User or Group option to add the new user. In the Select Users or Groups dialogue, find the user you wish to add and click OK. Click OK in the Log on as a service Properties to save the changes.
Perform the following to edit the Local Security Policy of the computer you want to define the ‘logon as a service’ permission: Logon to the computer with administrative privileges. In the right pane, right-click ‘Log on as a service’ and select properties.
Logon to the computer with administrative privileges. In the right pane, right-click ‘Log on as a service’ and select properties. Click on the ‘Add User or Group…’ button to add the new user. In the ‘Select Users or Groups’ dialogue, find the user you wish to enter and click ‘OK’ Click ‘OK’ in the ‘Log on as a service Properties’ to save changes.
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeServiceConfig(IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, String lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr OpenSCManager(
string machineName,
string databaseName,
uint dwAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean QueryServiceConfig(IntPtr hService, IntPtr intPtrQueryConfig, UInt32 cbBufSize, out UInt32 pcbBytesNeeded);
[StructLayout(LayoutKind.Sequential)]
public class QUERY_SERVICE_CONFIG
{
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwServiceType;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwStartType;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwErrorControl;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpBinaryPathName;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpLoadOrderGroup;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
public UInt32 dwTagID;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpDependencies;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpServiceStartName;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public String lpDisplayName;
};
private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;
private const uint SERVICE_QUERY_CONFIG = 0x00001;
private const uint SERVICE_CHANGE_CONFIG = 0x00002;
private const uint SERVICE_NO_CHANGE = 0xffffffff;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
public static void SetWindowsServiceCreds(string serviceName, string username, string password)
{
IntPtr hManager = IntPtr.Zero;
IntPtr hService = IntPtr.Zero;
try
{
hManager = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
if (hManager == IntPtr.Zero)
{
ThrowWin32Exception();
}
hService = OpenService(hManager, serviceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
if (hService == IntPtr.Zero)
{
ThrowWin32Exception();
}
if (!ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, username, password, null))
{
ThrowWin32Exception();
}
}
finally
{
if (hService != IntPtr.Zero) CloseServiceHandle(hService);
if (hManager != IntPtr.Zero) CloseServiceHandle(hManager);
}
}
private static void ThrowWin32Exception()
{
int error = Marshal.GetLastWin32Error();
Win32Exception e = new Win32Exception(error);
throw e;
}
This works as well:
void SetWindowsServiceCreds(string serviceName, string username, string password)
{
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
object[] wmiParams = new object[10];
wmiParams[6] = username;
wmiParams[7] = password;
service.InvokeMethod("Change", wmiParams);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With