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.