Tag Archive for WMI

Granting User Rights in C#

As a follow-up to my previous post about changing a Windows Service’s user account – there was one think I forgot.

In order for a user to run a service, that user must be granted the “Run as Service” right by the operating system. Usually it’s not a problem – the Services MMC snap-in automatically adds that right to a user we choose, and the ServiceProcessInstaller that we get when creating services in .NET also contains code to grant that right. The problem is when we’re doing it ourselves through our code – the Change() method on the Win32_Service WMI object doesn’t grant that right, and the only other WMI classes that seemed relevant, the RSoP classes, seem to be read-only classes that give us auditing and reports on what user rights are granted, but don’t let us manage them.

In other words, it’s back to P/Invoking. This time – the LsaOpenPolicy, LsaAddAccountRights and LsaClose methods.

Luckily for me, the work was already done. Much furious googling led me to a two year old forum post by MVP Willy Denoyette, with his managed wrapper class around these Win32 methods. It was written for .NET 1.1, probably, and uses some P/Invoke calls for things that have since been incorporated into .NET 2.0, like getting account SIDs. Never mind. It works fine, and that’s all I need.

Technically, I could build a list of constants for the specific logon rights, but for now this is the only one I need:

private static void GrantLogonAsServiceRight(string username)
{
   using (LsaWrapper lsa = new LsaWrapper())
   {
      lsa.AddPrivileges(username, “SeServiceLogonRight”);
   }
}

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);
}