Exemplo n.º 1
0
        internal AttachedCommand(
            Process process,
            bool throwOnError,
            TimeSpan timeout,
            CancellationToken cancellationToken,
            bool disposeOnExit)
        {
            this.process       = process;
            this.disposeOnExit = disposeOnExit;
            var processMonitoringTask = CreateProcessMonitoringTask(process);
            var processTask           = ProcessHelper.CreateProcessTask(this.process, processMonitoringTask, throwOnError, timeout, cancellationToken);

            this.commandResultTask = processTask.ContinueWith(
                continuedTask =>
            {
                if (disposeOnExit)
                {
                    this.process.Dispose();
                }
                return(new CommandResult(continuedTask.Result, this));
            },
                TaskContinuationOptions.ExecuteSynchronously
                );

            this.processes = new Lazy <ReadOnlyCollection <Process> >(() => new ReadOnlyCollection <Process>(new[] { this.process }));
        }
        internal ProcessCommand(
            ProcessStartInfo startInfo,
            bool throwOnError,
            bool disposeOnExit,
            TimeSpan timeout,
            CancellationToken cancellationToken,
            Encoding standardInputEncoding)
        {
            this.disposeOnExit = disposeOnExit;
            this.fileName      = startInfo.FileName;
            this.arguments     = startInfo.Arguments;
            this.process       = new Process {
                StartInfo = startInfo, EnableRaisingEvents = true
            };

            var processMonitoringTask = CreateProcessMonitoringTask(this.process);

            this.process.SafeStart(out var processStandardInput, out var processStandardOutput, out var processStandardError);

            var ioTasks = new List <Task>(capacity: 2);

            if (startInfo.RedirectStandardOutput)
            {
                this.standardOutputReader = new InternalProcessStreamReader(processStandardOutput);
                ioTasks.Add(this.standardOutputReader.Task);
            }
            if (startInfo.RedirectStandardError)
            {
                this.standardErrorReader = new InternalProcessStreamReader(processStandardError);
                ioTasks.Add(this.standardErrorReader.Task);
            }
            if (startInfo.RedirectStandardInput)
            {
                // unfortunately, changing the encoding can't be done via ProcessStartInfo so we have to do it manually here.
                // See https://github.com/dotnet/corefx/issues/20497

                var wrappedStream = PlatformCompatibilityHelper.WrapStandardInputStreamIfNeeded(processStandardInput.BaseStream);
                var standardInputEncodingToUse = standardInputEncoding ?? processStandardInput.Encoding;
                var streamWriter = wrappedStream == processStandardInput.BaseStream && Equals(standardInputEncodingToUse, processStandardInput.Encoding)
                    ? processStandardInput
                    : new StreamWriter(wrappedStream, standardInputEncodingToUse);
                this.standardInput = new ProcessStreamWriter(streamWriter);
            }

            // according to https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.id?view=netcore-1.1#System_Diagnostics_Process_Id,
            // this can throw PlatformNotSupportedException on some older windows systems in some StartInfo configurations. To be as
            // robust as possible, we thus make this a best-effort attempt
            try { this.processIdOrExceptionDispatchInfo = this.process.Id; }
            catch (PlatformNotSupportedException processIdException)
            {
                this.processIdOrExceptionDispatchInfo = ExceptionDispatchInfo.Capture(processIdException);
            }

            // we only set up timeout and cancellation AFTER starting the process. This prevents a race
            // condition where we immediately try to kill the process before having started it and then proceed to start it.
            // While we could avoid starting at all in such cases, that would leave the command in a weird state (no PID, no streams, etc)
            var processTask = ProcessHelper.CreateProcessTask(this.process, processMonitoringTask, throwOnError, timeout, cancellationToken);

            this.task = this.CreateCombinedTask(processTask, ioTasks);
        }