I'm using a thrid party Windows service that handles some automation tasks by running scripts and executables using CreateProcessAsUser(). I'm running into problems on Windows Server 2008 due to UAC and way the LUA elevation is handled through the APIs.
The service runs as LocalSystem and does not have "Interact With Desktop" enabled. The processes are being run as users in the Administrators group, but not the Administrator account (which is exempted from many UAC restrictions). All the UAC default settings in place.
I can pass arbitrary commands or powershell code to the service, but I can't seem to 'break out' of the non-elevated, non-interactive process that gets kicked off by the service.
The crux of the issue seems to be that the only (public) API option for starting an elevated process is ShellExecute() with the 'runas' verb, but as far as i can tell that can't be called from a non-interactive service or you get errors like "This operation requires an interactive window station".
The only workaround I've found is mentioned here: http://www.eggheadcafe.com/software/aspnet/29620442/how-to-proper-use-sendinp.aspx
In Vista, the official documented way to elevate a process is only using the shell API ShellExecute(Ex)(not CreateProcess or CreateProcessAsUser). So your application must call ShellExecute(Ex) to launch a helper elevated to call SendInput. Furthermore, due to Session 0 isolation, a service can only use CreateProcessAsUser or CreateProcessWithLogonW(can not use ShellExecute(Ex)) to specify the interactive desktop.
..I think there is no direct way to spawn an elevated process from a windows service. We can only first use CreateProcessAsUser or CreateProcessWithLogonW to spawn a non-elevated process into the user session(interactive desktop). Then in the non-elevated process, it may use ShellExecute(Ex) to spawn an elevated process for the real task.
To do this from .net/powershell code, it looks like I'd have to do some elaborate P/Invoke stuff to call CreateProcessAsUser or CreateProcessWithLogonW since the .Net System.Diagnostics.ProcessStartInfo doesn't have an equivalent of lpDesktop that I could set to "winsta0\default". And I'm not clear on if LocalSystem even has the rights to call CreateProcessAsUser or CreateProcessWithLogonW.
I also looked at http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx and http://stackoverflow.com/questions/2313553/process-start-with-different-credentials-with-uac-on
Based on all that, I'm reaching the conclusion that there's no straightforward way to do this. Am I missing something? This really doesn't seem like it should be so hard. It feels like UAC was just never designed to handle non-interactive use cases.
And if any Microsoft people end up reading this, I noticed that the way ShellExecute internally handles elevation is by calling out to Application Information Service (AIS). Why isn't that same call to AIS available through some Win32 or .NET API? http://msdn.microsoft.com/en-us/library/bb756945.aspx
Sorry that ran a bit long. Thanks for any ideas.