The Process.Start method in System.Diagnostics is equivalent to CreateProcess() in Win32. If you want to
launch a process as a different user, in Win32 you either need to call CreateProcessAsUser,
CreateProcessWithLogonW or CreateProcessWithTokenW. In .NET using Process.Start, you can use the
“runas” verb to the same thing.
If you have a .NET Service configured with the LocalSystem account, the “runas” verb doesn’t work and
you’ll encounter an exception and a failure of “access denied”.
Unhandled Exception: System.ComponentModel.Win32Exception: Access is denied
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
Internally what is happening is that .NET is using CreateProcessWithLogonW() to implement the
“runas” verb. If you take a look at the remarks for CreateProcessWithLogonW(), you’ll find the following,
“You cannot call CreateProcessWithLogonW from a process that is running under the "LocalSystem"
account, because the function uses the logon SID in the caller token, and the token for the "LocalSystem"
account does not contain this SID. As an alternative, use the CreateProcessAsUser and LogonUser functions.”
The reason this is happening is that CreateProcessWithLogonW() is assuming that the desktop of the
launched process is “Winsta0\Default”. This is known as the INTERACTIVE desktop. The security on this
desktop is based on the Logon SID associated with the INTERACTIVELY logged on user. (This is the
user who logged onto the system via CTRL-ALT-DELETE). The desktop associated with a LocalSystem
service is a hidden desktop. When CreateProcessWithLogonW() attempts to add the Logon SID from
the current user (LocalSystem), it won't find a LOGON SID (since LocalSystem doesn't have one).
This will cause CreateProcessWithLogonW() to fail with error code 5 or "access denied". Not only is
this an issue, CreateProcessWithLogonW() is assuming it is modifying "Winsta0\Default" which it isn't.