Setting Windows Service Account – C# and WMI

I’ve been busting my brains for over two hours trying to accomplish a relatively simple task – changing the username and password of a currently running Windows Service. Should be trivial enough, but the managed ServiceController class doesn’t give me that ability, so I had to resort to more esoteric solutions.

Assuming I wish to avoid direct registry manipulation – an easy enough choice to make – I can either P/Invoke the ChangeServiceConfig method (from advapi32.dll) or use System.Management and call the Win32_Service WMI class. I decided to use as little interop as possible and headed down the WMI path.

Now, Win32_Service doesn’t have a property for the user password, which makes sense for security reasons. What I can do is invoke the Change method on it, passing it the username and password. Unfortunately, Change accepts 11 different parameters that can be changed, most of which I wish to leave untouched.

I tried using MgmtClassGen.exe to generate a strongly-typed wrapper around Win32_Service, but the Change method is created for me needed work – it asked for an ErrorControl parameter as a Byte, for instance, but the ErrorControl property was strongly typed as a String – I had to start tweaking the parameters myself, receiving strange exceptions and potentially modifying properties I didn’t want to.

 Most code samples I could find refer to VBscript, which can simply not pass the parameters it doesn’t want, but C# isn’t as flexible. Ultimately, though, I decided to simulate this approach by simply passing null for any parameters I want untouched. This requires me to work without the MgmtClassGen class, and invoke the Change method untyped, like this. I can’t say it’s code I’m especially proud of, but it gets the work done.

string objPath = string.Format(“Win32_Service.Name='{0}'”, serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
   object[] wmiParams = new object[11];
   wmiParams[6] = username;
   wmiParams[7] = password;
   service.InvokeMethod(“Change”, wmiParams);

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.