Execute shell command from service Execute shell command from service shell shell

Execute shell command from service


If it's a windows app that requires the desktop, you're pretty much SOL. If it's a standard console application, you need to redirect standard input, standard output and standard error. You also need to set the ProcessStartInfo's UseShellExecute property to false: you service can't start the OS shell (cmd.exe) as that requires access to the desktop...and further, you can't redirect standard input with that property set to true.

Standard input is normally wired up to the keyboard. Your service does not have access to the keyboard. Standard out and standard error are normally wired up to the cmd.exe console window.

Once you have standard output and standard error redirected, you'll need to wire up handler to these Process object events:

  • Exited. Raised when the process ends.
  • OutputDataReceived. Raised when data is written to standard output by the process (in reality, occurs when any buffers on the output stream are flushed, so it may lag from the actual write operation).
  • ErrorDataReceived. Raised when data is written to standard error.

I tend to redirect standard output and standard error to the same stream and make sure that that stream is unbuffered. It's the equivalent of the cmd.exe incantation

some-command 2>&1

to redirect stdout and stderr into the same file handle.


As it turns out, the reason why this was not working was due to Application Compatibility - Session 0 Isolation. Essentially, the service launched the process as intended, but it was being launched inside of session 0, so it was hidden from the user, and as such, the user could not interact with it.

In order to get around this constraint, I was able to follow the guide Subverting Vista UAC in Both 32 and 64 bit Architectures written by Pero Matić. This brief guide allowed me to spawn a process from a service inside the currently logged on user's session, rather than inside of session 0. Sadly, I no longer have the completed code that I used to get this to work as the project I was using it for was cancelled.