public static SilentProcess StartConsoleProcessSilently(string exepath, string arguments, RedirectDataReceivedHandler stdoutHandler, RedirectDataReceivedHandler stderrHandler) { return(StartConsoleProcessSilentlyImpl(exepath, arguments, stdoutHandler, stderrHandler, false)); }
private static SilentProcess StartConsoleProcessSilentlyImpl(string exepath, string arguments, RedirectDataReceivedHandler stdoutHandler, RedirectDataReceivedHandler stderrHandler, bool combineStdoutAndStderr) { bool redirectstdout = false; bool redirectstderr = false; if (stdoutHandler != null) { redirectstdout = true; } if (stderrHandler != null && !combineStdoutAndStderr) { redirectstderr = true; } if (RunningOnWindows()) { //There is a bug in the System.Diagnostics.Process class that makes it //do this incorrectly, so we need to supply the correct implementation //Pipes for I/O Redirection IntPtr StdoutReadPipe = IntPtr.Zero; IntPtr StdoutWritePipe = IntPtr.Zero; IntPtr StderrReadPipe = IntPtr.Zero; IntPtr StderrWritePipe = IntPtr.Zero; STARTUPINFO StartInfo = new STARTUPINFO(); PROCESS_INFORMATION ProcessInfo; if (redirectstdout) { //Fill in the fields of the SecurityAttribitutes structure to pass in to CreatePipe SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES(); SecurityAttributes.nLength = Marshal.SizeOf(SecurityAttributes); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = IntPtr.Zero; //Create the Pipe CreatePipeNetEx(out StdoutReadPipe, out StdoutWritePipe, ref SecurityAttributes, 0); //Ensure the read handle is not inherited try { SetHandleInformationNetEx(StdoutReadPipe, HANDLE_FLAGS.INHERIT, (HANDLE_FLAGS)0); } catch { CloseHandleNetEx(StdoutReadPipe); CloseHandleNetEx(StdoutWritePipe); throw; } } try { if (redirectstderr) { //Fill in the fields of the SecurityAttribitutes structure to pass in to CreatePipe SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES(); SecurityAttributes.nLength = Marshal.SizeOf(SecurityAttributes); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = IntPtr.Zero; //Create the pipe CreatePipeNetEx(out StderrReadPipe, out StderrWritePipe, ref SecurityAttributes, 0); //Ensure the read handle is not inherited try { SetHandleInformationNetEx(StderrReadPipe, HANDLE_FLAGS.INHERIT, (HANDLE_FLAGS)0); } catch { CloseHandleNetEx(StderrReadPipe); CloseHandleNetEx(StderrWritePipe); throw; } } try { //Fill in the fields of the StartInfo structure to pass in to CreateProcess StartInfo.cb = Marshal.SizeOf(StartInfo); StartInfo.dwFlags = STARTF_USESHOWWINDOW; StartInfo.wShowWindow = SW_HIDE; if (redirectstderr || redirectstdout) { StartInfo.dwFlags |= STARTF_USESTDHANDLES; StartInfo.hStdError = IntPtr.Zero; StartInfo.hStdInput = IntPtr.Zero; StartInfo.hStdOutput = IntPtr.Zero; } if (redirectstdout) { StartInfo.hStdOutput = StdoutWritePipe; if (combineStdoutAndStderr) { StartInfo.hStdError = StdoutWritePipe; } } if (redirectstderr) { StartInfo.hStdError = StderrWritePipe; } //Call CreateProcess if (redirectstderr || redirectstdout) { if (!CreateProcess(null, string.Format("\"{0}\" {1}", exepath, arguments), IntPtr.Zero, IntPtr.Zero, true, CREATE_NEW_CONSOLE, IntPtr.Zero, null, ref StartInfo, out ProcessInfo)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { if (!CreateProcess(null, string.Format("\"{0}\" {1}", exepath, arguments), IntPtr.Zero, IntPtr.Zero, false, CREATE_NEW_CONSOLE, IntPtr.Zero, null, ref StartInfo, out ProcessInfo)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } //Close the Handles // CloseHandleNetEx(ProcessInfo.hThread); //Create the redirection threads if (redirectstdout) { RedirectReadLoop stdoutLoop = new RedirectReadLoop(); stdoutLoop.RedirectedPipe = StdoutReadPipe; stdoutLoop.handler = stdoutHandler; //The child has its own handle for the write side of the pipe //so we should close ours so the pipe will "break" when the child //shuts down, giving us indication to stop the read loop. CloseHandleNetEx(StdoutWritePipe); Thread t = new Thread(new ThreadStart(stdoutLoop.ReadLoop)); t.Start(); } if (redirectstderr) { RedirectReadLoop stderrLoop = new RedirectReadLoop(); stderrLoop.RedirectedPipe = StderrReadPipe; stderrLoop.handler = stderrHandler; //The child has its own handle for the write side of the pipe //so we should close ours so the pipe will "break" when the child //shuts down, giving us indication to stop the read loop. CloseHandleNetEx(StderrWritePipe); Thread t = new Thread(new ThreadStart(stderrLoop.ReadLoop)); t.Start(); } return(new SilentProcess(ProcessInfo.hProcess, null)); } catch { if (redirectstderr) { CloseHandleNetEx(StderrReadPipe); CloseHandleNetEx(StderrWritePipe); } throw; } } catch { if (redirectstdout) { CloseHandleNetEx(StdoutReadPipe); CloseHandleNetEx(StdoutWritePipe); } throw; } } else { //On UNIX we can use the built in implementation ProcessStartInfo info = new ProcessStartInfo(exepath, arguments); info.CreateNoWindow = true; info.WindowStyle = ProcessWindowStyle.Hidden; info.UseShellExecute = false; Process process = new Process(); DataReceivedEventHandlerWrapper stdoutWrapper = null; DataReceivedEventHandlerWrapper stderrWrapper = null; if (redirectstdout) { info.RedirectStandardOutput = true; stdoutWrapper = new DataReceivedEventHandlerWrapper(); stdoutWrapper.wrapped = stdoutHandler; DataReceivedEventHandler handler = new DataReceivedEventHandler(stdoutWrapper.Handle); process.OutputDataReceived += handler; if (combineStdoutAndStderr) { info.RedirectStandardError = true; process.ErrorDataReceived += handler; } } if (redirectstderr) { info.RedirectStandardError = true; stderrWrapper = new DataReceivedEventHandlerWrapper(); stderrWrapper.wrapped = stderrHandler; DataReceivedEventHandler handler = new DataReceivedEventHandler(stderrWrapper.Handle); process.ErrorDataReceived += handler; } process.StartInfo = info; process.Start(); if (redirectstdout) { process.BeginOutputReadLine(); } if (redirectstderr || (redirectstdout && combineStdoutAndStderr)) { process.BeginErrorReadLine(); } return(new SilentProcess(IntPtr.Zero, process)); } }
public static SilentProcess StartConsoleProcessSilently(string exepath, string arguments, RedirectDataReceivedHandler outputHandler) { return(StartConsoleProcessSilentlyImpl(exepath, arguments, outputHandler, null, true)); }