Uses character by character parsing for StandardOutput and StandardError, so \r can be processed. Uses observables instead of eventhandlers. Do not call BeginReadStandardOutput and BeginReadStandardError etc
Inheritance: System.Diagnostics.Process
        async Task<ProcessExitResult> LaunchAndWaitForExitAsync(ReactiveProcess process, TimeSpan? monitorOutput,
            TimeSpan? monitorResponding) {
            var task = process.StartAsync();
            _launched.OnNext(Tuple.Create(process.StartInfo, process.Id));

            using (SetupMonitoringDisposable(process, monitorOutput, monitorResponding))
                await task.ConfigureAwait(false);
            _terminated.OnNext(Tuple.Create(process.StartInfo, process.ExitCode, process.Id));
            return new ProcessExitResult(process.ExitCode, process.Id, process.StartInfo);
        }
        async Task<ProcessExitResult> LaunchAndWaitForExitAsync(ReactiveProcess process, TimeSpan? monitorOutput,
            TimeSpan? monitorResponding, CancellationToken token) {
            var task = process.StartAsync();
            _launched.OnNext(Tuple.Create(process.StartInfo, process.Id));

            using (SetupMonitoringDisposable(process, monitorOutput, monitorResponding))
            using (token.Register(process.TryKill))
                await task.ConfigureAwait(false);
            _terminated.OnNext(Tuple.Create(process.StartInfo, process.ExitCode, process.Id));
            token.ThrowIfCancellationRequested();
            return new ProcessExitResult(process.ExitCode, process.Id, process.StartInfo);
        }
 static IDisposable SetupStandardOutput(LaunchAndProcessInfo info, ReactiveProcess process) {
     if (!info.StartInfo.RedirectStandardOutput)
         throw new InvalidOperationException("Not redirected output");
     var dsp = new CompositeDisposable();
     if (info.StandardOutputObs != null)
         dsp.Add(info.StandardOutputObs(process.StandardOutputObservable));
     if (info.StandardOutputAction != null)
         dsp.Add(process.StandardOutputObservable.Subscribe(data => info.StandardOutputAction(process, data)));
     return dsp;
 }
 public async Task<ProcessExitResult> LaunchAndProcessAsync(LaunchAndProcessInfo info) {
     using (var process = new ReactiveProcess {StartInfo = info.StartInfo.EnableRedirect()}) {
         using (SetupStandardOutput(info, process))
         using (SetupStandardError(info, process))
             return
                 await
                     LaunchAndWaitForExitAsync(process, info.MonitorOutput, info.MonitorResponding,
                             info.CancellationToken)
                         .ConfigureAwait(false);
     }
 }
 public async Task<ProcessExitResult> LaunchElevatedAsync(BasicLaunchInfo info) {
     info.StartInfo.EnableRunAsAdministrator();
     ProcessBLI(info);
     using (var process = new ReactiveProcess {StartInfo = info.StartInfo}) {
         return
             await
                 LaunchAndWaitForExitAsync(process, info.MonitorOutput, info.MonitorResponding,
                         info.CancellationToken)
                     .ConfigureAwait(false);
     }
 }
        Timer MonitorProcessOutput(ReactiveProcess process, TimeSpan timeout) {
            Contract.Requires<ArgumentNullException>(process != null);
            Contract.Requires<ArgumentNullException>(timeout != null);

            var state = process.MonitorProcessOutput();
            _monitorStarted.OnNext(Tuple.Create(process.StartInfo, process.Id, "Output"));
            return new TimerWithElapsedCancellation(monitorInterval,
                () => OnOutputMonitorElapsed(process, state, timeout),
                () => _monitorStopped.OnNext(Tuple.Create(process.StartInfo, process.Id, "Output")));
        }
        CompositeDisposable SetupMonitoringDisposable(ReactiveProcess process, TimeSpan? monitorOutput,
            TimeSpan? monitorResponding) {
            var disposable = new CompositeDisposable();
            if (monitorOutput.HasValue)
                disposable.Add(MonitorProcessOutput(process, monitorOutput.Value));
            //if (monitorResponding.HasValue)
                //disposable.Add(MonitorProcessResponding(process, monitorResponding.Value));

            return disposable;
        }