C# and .NET 3.5 - How to launch a process using different credentials, with a hidden window, and being able to capture standard output and exit code?

笑着哭i 提交于 2020-01-13 13:11:09

问题


I have a Windows Service developed in C# and .NET 3.5 to perform various administrative tasks throughout our 3 domains. I've got an admin account in each domain that has the necessary rights/permissions for what this service is doing.

For all the AD interactions, I can bind to AD using the correct username/password for the domain and all is good. However, I have a need now to launch an external process (robocopy) to perform some work and I cannot find any code examples anywhere for doing this in .NET 3.5.

What I need to do is launch robocopy using alternate credentials in a hidden window, capture the standard output so I have a log of what was actually done, and capture the exit code so I can tell if it was successful.

I found some old .NET 1.1 code from K. Scott Allen's blog (see the last few comments for a good code listing) that extends the System.Diagnostics.Process object and calls the Win32 API function CreateProcessAsUserW. However, the code doesn't work due to some API changes in .NET 2.0. Using the code snippet from the last comment on the referenced blog where it is using reflection to call the private SetProcessHandle function of the Process object causes Access Denied errors when I try to interact with the process (to kill it or get exit code).

Does anyone have a good example of how to accomplish this?

EDIT: The built-in .NET Process and ProcessStartInfo API does allow you to specify alternate credentials but when you do, it wants to create a visible window (even if you specify CreateNoWindow or WindowStyle Hidden) which fails when running as a Windows Service. So those are not an option for this application. Impersonation doesn't work either since when the external process is launched, it uses the credentials of the parent process, not the impersonated credentials.

SOLUTION: As Reed pointed out below, P/Invoke using one of the Win32 API functions should allow you to make this happen. I ended up going a slightly different route using an old freeware NT4 utility called RunProcess that allows you to specify a username/password on the command line. It worked on Vista and 2k3 and also worked correctly when launched by a windows service running as Local System.


回答1:


I think you want to look at:

ProcessStartInfo

That provides a .NET only way to start a process under a different user with different credentials. No more need for the Win32 API.

--- EDIT ---

Other alternatives might be to use the P/Invoke as specified here (look at the note at the bottom first) or more likely, using P/Invoke with CreateProcessWithLogonW.




回答2:


Just an unverified thought, but isn't using dynamic Impersonate valid for the entire code block in .net 2+? So Impersonate the required user and then do whatever you need within the impersonated context/scope, like starting a process the normal way? Think we did something like that to integrate mstsc.exe launching using already supplied credentials.




回答3:


StartInfo has a property called CreateNoWindow that may make Reed's suggestion work for you.




回答4:


If you want to see those exit codes actually used, have a look at www.robocopyplus.com. it acts like a wrapper around robocopy to add swicthes for email notification and report filtering. This may already do some of the stuff you are trying to achieve.




回答5:


This should work well with the Process class and ProcessStartInfo.

Different credentials:

  • ProcessStartInfo.UserName Property
  • ProcessStartInfo.Password Property

Redirect standard output:

  • ProcessStartInfo.RedirectStandardOutput Property
  • Process.StandardOutput Property

Exit code:

  • Process.ExitCode Property


来源:https://stackoverflow.com/questions/643723/c-sharp-and-net-3-5-how-to-launch-a-process-using-different-credentials-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!