public static Action ExcuteUntilExitOrCancellation(
            CancellationToken aCancellationToken,
            ShellParameters aShellParameters,
            Action <string> aActOnProcessOutput)
        {
            return(() =>
            {
                using (Process lBackgroundProcess = BackgroundProcesses.SetBackgroundProcessRunning(aShellParameters))
                {
                    // Start a task to read all of STDOUT from the background process.  The process will exit
                    // if and when the process closes STDOUT and this task reads it to the end.
                    Task <string> lReadingStdout = lBackgroundProcess.StandardOutput.ReadToEndAsync();

                    // Wait on the task.  If the task is cancelled, an OperationCanceledException will be raised.
                    // If the task is cancelled, the background process probably hasn't exited, so try to kill it,
                    // else it won't exit.
                    try
                    {
                        lReadingStdout.Wait(aCancellationToken);
                    }
                    catch (System.OperationCanceledException)
                    {
                        BackgroundProcesses.AttemptToKill(lBackgroundProcess);
                    }

                    aActOnProcessOutput(lReadingStdout.Result);
                }
            });
        }
        public static Process SetBackgroundProcessRunning(ShellParameters aParameters)
        {
            Process lProcess = new System.Diagnostics.Process();

            lProcess.StartInfo.WorkingDirectory       = Path.GetTempPath();
            lProcess.StartInfo.UseShellExecute        = false;
            lProcess.StartInfo.FileName               = aParameters.Executable;
            lProcess.StartInfo.RedirectStandardInput  = true;
            lProcess.StartInfo.RedirectStandardOutput = true;
            lProcess.StartInfo.CreateNoWindow         = true;
            if (aParameters.Arguments != null && aParameters.Arguments.Length > 0)
            {
                lProcess.StartInfo.Arguments = aParameters.Arguments;
            }

            lProcess.Start();
            lProcess.StandardInput.WriteLine(aParameters.StandardInput);
            lProcess.StandardInput.Close();

            return(lProcess);
        }