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())