views:

2019

answers:

5

I have a Windows service that runs as mydomain\userA. I want to be able to run arbitrary .exes from the service. Normally, I use Process.Start() and it works fine, but in some cases I want to run the executable as a different user (mydomain\userB).

If I change the ProcessStartInfo I use to start the process to include credentials, I start getting errors - either an error dialog box that says "The application failed to initialize properly (0xc0000142). Click on OK to terminate the application.", or an "Access is denied" Win32Exception. If I run the process-starting code from the command-line instead of running it in the service, the process starts using the correct credentials (I've verified this by setting the ProcessStartInfo to run whoami.exe and capturing the command-line output).

I've also tried impersonation using WindowsIdentity.Impersonate(), but this hasn't worked - as I understand it, impersonation only affects the current thread, and starting a new process inherits the process' security descriptor, not the current thread.

I'm running this in an isolated test domain, so both userA and userB are domain admins, and both have the Log On as a Service right domain-wide.

A: 

How are you setting the domain, user, and password? Are you setting the domain properly as well as the password (it must use a SecureString).

Also, are you setting the WorkingDirectory property? When using a UserName and Password, the documentation states that you must set the WorkingDirectory property.

casperOne
I'm setting domain, username and password (as a SecureString) correctly - if I run this code outside of the Windows service, it works as expected. Setting the WorkingDirectory doesn't seem to have any affect, either.
Zack Elan
+2  A: 

This is symptomatic of :
- insufficient rights;
- failure load of a library;

Use Filemon to detect some access denied or
WinDbg to run the application in a debugger and view any issue.

lsalamon
*now* i read your answer... +1 for the Filemon reference, I think that will point out the problem.
Moose
A: 

It may be that any process kicked off by a service must also have the "Log on as a Service" privelege.

If the user id that you are using to start the second process does not have administrative rights to the box, this could be the case.

An easy test would be to change the local security policy to give the userid "Log on as a service" and try it again.

Edit: After the additional info..

Grazing over Google on this one, it appears that 0xc0000142 relates to not being able to initialize a needed DLL. Is there something that the service has open that the spawned process needs? In any case, it looks like it has to do with the process that's kicked off, and not how you are doing it.

Moose
Both users have Log on as a Service enabled.
Zack Elan
Added some more to my answer. It looks like you may have some conflicts between the service and the spawned process based on the 0xc0000142 error.
Moose
+4  A: 

When you launch a new process using ProcessStartInfo the process is started in the same window station and desktop as the launching process. If you are using different credentials then the user will, in general, not have sufficient rights to run in that desktop. The failure to initialize errors are caused when user32.dll attempts to initialize in the new process and can't.

To get around this you must first retrieve the security descriptors associated with the window station and desktop and add the appropriate permissions to the DACL for your user, then launch your process under the new credentials.

EDIT: A detailed description on how to do this and sample code was a little long for here so I put together an article with code.

Stephen Martin
Thanks; it looks like this is the cause of the problem. Do you have any suggestions on the best way to retrieve the DACL and add permissions for the 2nd user?
Zack Elan
You don't need to set the Window Station and Desktop DACLs if you create the service interactive.
Adam Ruth
A: 

I had this problem today, and I spent quite some time trying to figure it out. What I ended up doing was to create the service as interactive (using the Allow service to interact with desktop checkbox in services.msc). As soon as I did that the 0xc0000142 errors went away.

Adam Ruth