bool ExecuteProcess(string val, IExecutionToken executionToken, out StreamReader errorReader, out StringBuilder outputReader)
{
outputReader = new StringBuilder();
_process = new Process();
using (_process)
{
var processStartInfo = CreateProcessStartInfo(val);
if (processStartInfo == null)
{
// ReSharper disable NotResolvedInText
throw new ArgumentNullException("processStartInfo");
// ReSharper restore NotResolvedInText
}
_process.StartInfo = processStartInfo;
var processStarted = _process.Start();
StringBuilder reader = outputReader;
errorReader = _process.StandardError;
if (!ProcessHasStarted(processStarted, _process))
{
return(false);
}
if (!_process.HasExited)
{
_process.PriorityClass = CommandPriority;
}
_process.StandardInput.Close();
// bubble user termination down the chain ;)
while (!_process.HasExited && !executionToken.IsUserCanceled)
{
reader.Append(_process.StandardOutput.ReadToEnd());
if (!_process.HasExited && _process.Threads.Cast <ProcessThread>().Any(a => a.ThreadState == System.Diagnostics.ThreadState.Wait && a.WaitReason == ThreadWaitReason.UserRequest))
{
//reader.Append(_process.StandardOutput.ReadToEnd());
_process.Kill();
}
else if (!_process.HasExited)
{
var isWaitingForUserInput = ModalChecker.IsWaitingForUserInput(_process);
if (!isWaitingForUserInput)
{
continue;
}
//_process.OutputDataReceived -= a;
_process.Kill();
throw new ApplicationException("The process required user input.");
}
Thread.Sleep(10);
}
// user termination exit ;)
if (executionToken.IsUserCanceled)
{
// darn .Kill() does not kill the process tree ;(
// Nor does .CloseMainWindow() as people have claimed, hence the hand rolled process tree killer - WTF M$ ;(
KillProcessAndChildren(_process.Id);
}
reader.Append(_process.StandardOutput.ReadToEnd());
//_process.OutputDataReceived -= a;
_process.Close();
}
return(true);
}