internal ProcessStreamReader(StreamReader streamReader, string processPath, bool isOutput, PipelineWriter writer, ProcessOutputReader processOutputReader) { this.streamReader = streamReader; this.processPath = processPath; this.isOutput = isOutput; this.writer = writer; this.processOutputReader = processOutputReader; }
internal ProcessStreamReader(StreamReader streamReader, string processPath, bool isOutput, PipelineWriter writer, ProcessOutputReader processOutputReader) { this.streamReader = streamReader; this.processPath = processPath; this.isOutput = isOutput; this.writer = writer; this.processOutputReader = processOutputReader; }
internal ProcessStreamReader( StreamReader streamReader, string processPath, bool isOutput, PipelineWriter writer, ProcessOutputReader processOutputReader) { using (ProcessStreamReader.tracer.TraceConstructor((object)this, " isOutput {0}", (object)isOutput)) { this.streamReader = streamReader; this.processPath = processPath; this.isOutput = isOutput; this.writer = writer; this.processOutputReader = processOutputReader; } }
/// <summary> /// Executes the native command once all of the input has been gathered. /// </summary> /// <exception cref="PipelineStoppedException"> /// The pipeline is stopping /// </exception> /// <exception cref="ApplicationFailedException"> /// The native command could not be run /// </exception> internal override void Complete() { // Indicate whether we need to consider redirecting the output/error of the current native command. // Usually a windows program which is the last command in a pipeline can be executed as 'background' -- we don't need to capture its output/error streams. bool background; // Figure out if we're going to run this process "standalone" i.e. without // redirecting anything. This is a bit tricky as we always run redirected so // we have to see if the redirection is actually being done at the topmost level or not. //Calculate if input and output are redirected. bool redirectOutput; bool redirectError; bool redirectInput; CalculateIORedirection(out redirectOutput, out redirectError, out redirectInput); // Find out if it's the only command in the pipeline. bool soloCommand = this.Command.MyInvocation.PipelineLength == 1; // Get the start info for the process. ProcessStartInfo startInfo = GetProcessStartInfo(redirectOutput, redirectError, redirectInput, soloCommand); if (this.Command.Context.CurrentPipelineStopping) { throw new PipelineStoppedException(); } // If a problem occurred in running the program, this exception will // be set and should be rethrown at the end of the try/catch block... Exception exceptionToRethrow = null; Host.Coordinates startPosition = new Host.Coordinates(); bool scrapeHostOutput = false; try { // If this process is being run standalone, tell the host, which might want // to save off the window title or other such state as might be tweaked by // the native process if (!redirectOutput) { this.Command.Context.EngineHostInterface.NotifyBeginApplication(); // Also, store the Raw UI coordinates so that we can scrape the screen after // if we are transcribing. try { if (this.Command.Context.EngineHostInterface.UI.IsTranscribing) { scrapeHostOutput = true; startPosition = this.Command.Context.EngineHostInterface.UI.RawUI.CursorPosition; startPosition.X = 0; } } catch (Host.HostException) { // The host doesn't support scraping via its RawUI interface scrapeHostOutput = false; } } //Start the process. If stop has been called, throw exception. //Note: if StopProcessing is called which this method has the lock, //Stop thread will wait for nativeProcess to start. //If StopProcessing gets the lock first, then it will set the stopped //flag and this method will throw PipelineStoppedException when it gets //the lock. lock (_sync) { if (_stopped) { throw new PipelineStoppedException(); } try { _nativeProcess = new Process(); _nativeProcess.StartInfo = startInfo; _nativeProcess.Start(); } catch (Win32Exception) { #if CORECLR // Shell doesn't exist on OneCore, so a file cannot be associated with an executable, // and we cannot run an executable as 'ShellExecute' either. throw; #else // See if there is a file association for this command. If so // then we'll use that. If there's no file association, then // try shell execute... string executable = FindExecutable(startInfo.FileName); bool notDone = true; if (!String.IsNullOrEmpty(executable)) { if (IsConsoleApplication(executable)) { // Allocate a console if there isn't one attached already... ConsoleVisibility.AllocateHiddenConsole(); } string oldArguments = startInfo.Arguments; string oldFileName = startInfo.FileName; startInfo.Arguments = "\"" + startInfo.FileName + "\" " + startInfo.Arguments; startInfo.FileName = executable; try { _nativeProcess.Start(); notDone = false; } catch (Win32Exception) { // Restore the old filename and arguments to try shell execute last... startInfo.Arguments = oldArguments; startInfo.FileName = oldFileName; } } // We got here because there was either no executable found for this // file or we tried to launch the exe and it failed. In either case // we will try launching one last time using ShellExecute... if (notDone) { if (soloCommand && startInfo.UseShellExecute == false) { startInfo.UseShellExecute = true; startInfo.RedirectStandardInput = false; startInfo.RedirectStandardOutput = false; startInfo.RedirectStandardError = false; _nativeProcess.Start(); } else { throw; } } #endif } } if (this.Command.MyInvocation.PipelinePosition < this.Command.MyInvocation.PipelineLength) { // Never background unless you're at the end of a pipe. // Something like // ls | notepad | sort.exe // should block until the notepad process is terminated. background = false; } else { background = true; if (startInfo.UseShellExecute == false) { background = IsWindowsApplication(_nativeProcess.StartInfo.FileName); } } try { //If input is redirected, start input to process. if (startInfo.RedirectStandardInput) { NativeCommandIOFormat inputFormat = NativeCommandIOFormat.Text; if (_isMiniShell) { inputFormat = ((MinishellParameterBinderController)NativeParameterBinderController).InputFormat; } lock (_sync) { if (!_stopped) { _inputWriter.Start(_nativeProcess, inputFormat); } } } if (background == false) { //if output is redirected, start reading output of process. if (startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { lock (_sync) { if (!_stopped) { _outputReader = new ProcessOutputReader(_nativeProcess, Path, redirectOutput, redirectError); _outputReader.Start(); } } if (_outputReader != null) { ProcessOutputHelper(); } } } } catch (Exception) { StopProcessing(); throw; } finally { if (background == false) { //Wait for process to exit _nativeProcess.WaitForExit(); //Wait for input writer to finish. _inputWriter.Done(); //Wait for outputReader to finish if (_outputReader != null) { _outputReader.Done(); } // Capture screen output if we are transcribing if (this.Command.Context.EngineHostInterface.UI.IsTranscribing && scrapeHostOutput) { Host.Coordinates endPosition = this.Command.Context.EngineHostInterface.UI.RawUI.CursorPosition; endPosition.X = this.Command.Context.EngineHostInterface.UI.RawUI.BufferSize.Width - 1; // If the end position is before the start position, then capture the entire buffer. if (endPosition.Y < startPosition.Y) { startPosition.Y = 0; } Host.BufferCell[,] bufferContents = this.Command.Context.EngineHostInterface.UI.RawUI.GetBufferContents( new Host.Rectangle(startPosition, endPosition)); StringBuilder lineContents = new StringBuilder(); StringBuilder bufferText = new StringBuilder(); for (int row = 0; row < bufferContents.GetLength(0); row++) { if (row > 0) { bufferText.Append(Environment.NewLine); } lineContents.Clear(); for (int column = 0; column < bufferContents.GetLength(1); column++) { lineContents.Append(bufferContents[row, column].Character); } bufferText.Append(lineContents.ToString().TrimEnd(Utils.Separators.SpaceOrTab)); } this.Command.Context.InternalHost.UI.TranscribeResult(bufferText.ToString()); } this.Command.Context.SetVariable(SpecialVariables.LastExitCodeVarPath, _nativeProcess.ExitCode); if (_nativeProcess.ExitCode != 0) this.commandRuntime.PipelineProcessor.ExecutionFailed = true; } } } catch (Win32Exception e) { exceptionToRethrow = e; } // try catch (PipelineStoppedException) { // If we're stopping the process, just rethrow this exception... throw; } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); exceptionToRethrow = e; } finally { if (!redirectOutput) { this.Command.Context.EngineHostInterface.NotifyEndApplication(); } // Do the clean up... CleanUp(); } // An exception was thrown while attempting to run the program // so wrap and rethrow it here... if (exceptionToRethrow != null) { // It's a system exception so wrap it in one of ours and re-throw. string message = StringUtil.Format(ParserStrings.ProgramFailedToExecute, this.NativeCommandName, exceptionToRethrow.Message, this.Command.MyInvocation.PositionMessage); ApplicationFailedException appFailedException = new ApplicationFailedException(message, exceptionToRethrow); // There is no need to set this exception here since this exception will eventually be caught by pipeline processor. // this.commandRuntime.PipelineProcessor.ExecutionFailed = true; throw appFailedException; } }
/// <summary> /// Creates an instance of ProcessStreamReader /// </summary> /// <param name="streamReader"> /// Stream from which data is read /// </param> /// <param name="processPath"> /// Path to the process. This is used for setting the name of the thread. /// </param> /// <param name="isOutput"> /// if true stream is output stream of process /// else stream is error stream. /// </param> /// <param name="writer"> /// Processed data is written to it /// </param> /// <param name="processOutputReader"> /// ProcessOutputReader which owns this stream reader /// </param> internal ProcessStreamReader(StreamReader streamReader, string processPath, bool isOutput, PipelineWriter writer, ProcessOutputReader processOutputReader) { Dbg.Assert(streamReader != null, "Caller should validate the parameter"); Dbg.Assert(processPath != null, "Caller should validate the parameter"); Dbg.Assert(writer != null, "Caller should validate the parameter"); Dbg.Assert(processOutputReader != null, "Caller should validate the parameter"); _streamReader = streamReader; _processPath = processPath; _isOutput = isOutput; _writer = writer; _processOutputReader = processOutputReader; }
internal override void Complete() { bool flag2; bool flag3; bool flag4; if (base.Context._debuggingMode > 0) { base.Context.Debugger.CheckCommand(base.Command.MyInvocation); } this.CalculateIORedirection(out flag2, out flag3, out flag4); bool soloCommand = base.Command.MyInvocation.PipelineLength == 1; ProcessStartInfo info = this.GetProcessStartInfo(flag2, flag3, flag4, soloCommand); if (base.Command.Context.CurrentPipelineStopping) { throw new PipelineStoppedException(); } Exception innerException = null; try { bool flag; if (!flag2) { base.Command.Context.EngineHostInterface.NotifyBeginApplication(); } lock (this.sync) { if (this.stopped) { throw new PipelineStoppedException(); } try { this.nativeProcess = new Process(); this.nativeProcess.StartInfo = info; this.nativeProcess.Start(); } catch (Win32Exception) { string str = FindExecutable(info.FileName); bool flag6 = true; if (!string.IsNullOrEmpty(str)) { if (IsConsoleApplication(str)) { ConsoleVisibility.AllocateHiddenConsole(); } string arguments = info.Arguments; string fileName = info.FileName; info.Arguments = "\"" + info.FileName + "\" " + info.Arguments; info.FileName = str; try { this.nativeProcess.Start(); flag6 = false; } catch (Win32Exception) { info.Arguments = arguments; info.FileName = fileName; } } if (flag6) { if (!soloCommand || info.UseShellExecute) { throw; } info.UseShellExecute = true; info.RedirectStandardInput = false; info.RedirectStandardOutput = false; info.RedirectStandardError = false; this.nativeProcess.Start(); } } } if (base.Command.MyInvocation.PipelinePosition < base.Command.MyInvocation.PipelineLength) { flag = false; } else { flag = true; if (!info.UseShellExecute) { flag = IsWindowsApplication(this.nativeProcess.StartInfo.FileName); } } try { if (info.RedirectStandardInput) { NativeCommandIOFormat text = NativeCommandIOFormat.Text; if (this.isMiniShell) { text = ((MinishellParameterBinderController)this.NativeParameterBinderController).InputFormat; } lock (this.sync) { if (!this.stopped) { this.inputWriter.Start(this.nativeProcess, text); } } } if (!flag && (info.RedirectStandardOutput || info.RedirectStandardError)) { lock (this.sync) { if (!this.stopped) { this.outputReader = new ProcessOutputReader(this.nativeProcess, this.Path, flag2, flag3); this.outputReader.Start(); } } if (this.outputReader != null) { this.ProcessOutputHelper(); } } } catch (Exception) { this.StopProcessing(); throw; } finally { if (!flag) { this.nativeProcess.WaitForExit(); this.inputWriter.Done(); if (this.outputReader != null) { this.outputReader.Done(); } base.Command.Context.SetVariable(SpecialVariables.LastExitCodeVarPath, this.nativeProcess.ExitCode); if (this.nativeProcess.ExitCode != 0) { base.commandRuntime.PipelineProcessor.ExecutionFailed = true; } } } } catch (Win32Exception exception2) { innerException = exception2; } catch (PipelineStoppedException) { throw; } catch (Exception exception3) { CommandProcessorBase.CheckForSevereException(exception3); innerException = exception3; } finally { if (!flag2) { base.Command.Context.EngineHostInterface.NotifyEndApplication(); } this.CleanUp(); } if (innerException != null) { string message = StringUtil.Format(ParserStrings.ProgramFailedToExecute, new object[] { this.NativeCommandName, innerException.Message, base.Command.MyInvocation.PositionMessage }); if (message == null) { message = StringUtil.Format("Program '{0}' failed to execute: {1}{2}", new object[] { this.NativeCommandName, innerException.Message, base.Command.MyInvocation.PositionMessage }); } ApplicationFailedException exception4 = new ApplicationFailedException(message, innerException); throw exception4; } }
internal override void Complete() { bool flag2; bool flag3; bool flag4; if (base.Context._debuggingMode > 0) { base.Context.Debugger.CheckCommand(base.Command.MyInvocation); } this.CalculateIORedirection(out flag2, out flag3, out flag4); bool soloCommand = base.Command.MyInvocation.PipelineLength == 1; ProcessStartInfo info = this.GetProcessStartInfo(flag2, flag3, flag4, soloCommand); if (base.Command.Context.CurrentPipelineStopping) { throw new PipelineStoppedException(); } Exception innerException = null; try { bool flag; if (!flag2) { base.Command.Context.EngineHostInterface.NotifyBeginApplication(); } lock (this.sync) { if (this.stopped) { throw new PipelineStoppedException(); } try { this.nativeProcess = new Process(); this.nativeProcess.StartInfo = info; this.nativeProcess.Start(); } catch (Win32Exception) { string str = FindExecutable(info.FileName); bool flag6 = true; if (!string.IsNullOrEmpty(str)) { if (IsConsoleApplication(str)) { ConsoleVisibility.AllocateHiddenConsole(); } string arguments = info.Arguments; string fileName = info.FileName; info.Arguments = "\"" + info.FileName + "\" " + info.Arguments; info.FileName = str; try { this.nativeProcess.Start(); flag6 = false; } catch (Win32Exception) { info.Arguments = arguments; info.FileName = fileName; } } if (flag6) { if (!soloCommand || info.UseShellExecute) { throw; } info.UseShellExecute = true; info.RedirectStandardInput = false; info.RedirectStandardOutput = false; info.RedirectStandardError = false; this.nativeProcess.Start(); } } } if (base.Command.MyInvocation.PipelinePosition < base.Command.MyInvocation.PipelineLength) { flag = false; } else { flag = true; if (!info.UseShellExecute) { flag = IsWindowsApplication(this.nativeProcess.StartInfo.FileName); } } try { if (info.RedirectStandardInput) { NativeCommandIOFormat text = NativeCommandIOFormat.Text; if (this.isMiniShell) { text = ((MinishellParameterBinderController) this.NativeParameterBinderController).InputFormat; } lock (this.sync) { if (!this.stopped) { this.inputWriter.Start(this.nativeProcess, text); } } } if (!flag && (info.RedirectStandardOutput || info.RedirectStandardError)) { lock (this.sync) { if (!this.stopped) { this.outputReader = new ProcessOutputReader(this.nativeProcess, this.Path, flag2, flag3); this.outputReader.Start(); } } if (this.outputReader != null) { this.ProcessOutputHelper(); } } } catch (Exception) { this.StopProcessing(); throw; } finally { if (!flag) { this.nativeProcess.WaitForExit(); this.inputWriter.Done(); if (this.outputReader != null) { this.outputReader.Done(); } base.Command.Context.SetVariable(SpecialVariables.LastExitCodeVarPath, this.nativeProcess.ExitCode); if (this.nativeProcess.ExitCode != 0) { base.commandRuntime.PipelineProcessor.ExecutionFailed = true; } } } } catch (Win32Exception exception2) { innerException = exception2; } catch (PipelineStoppedException) { throw; } catch (Exception exception3) { CommandProcessorBase.CheckForSevereException(exception3); innerException = exception3; } finally { if (!flag2) { base.Command.Context.EngineHostInterface.NotifyEndApplication(); } this.CleanUp(); } if (innerException != null) { string message = StringUtil.Format(ParserStrings.ProgramFailedToExecute, new object[] { this.NativeCommandName, innerException.Message, base.Command.MyInvocation.PositionMessage }); if (message == null) { message = StringUtil.Format("Program '{0}' failed to execute: {1}{2}", new object[] { this.NativeCommandName, innerException.Message, base.Command.MyInvocation.PositionMessage }); } ApplicationFailedException exception4 = new ApplicationFailedException(message, innerException); throw exception4; } }
internal override void Complete() { bool redirectOutput; bool redirectError; bool redirectInput; this.CalculateIORedirection(out redirectOutput, out redirectError, out redirectInput); bool soloCommand = this.Command.MyInvocation.PipelineLength == 1; ProcessStartInfo processStartInfo = this.GetProcessStartInfo(redirectOutput, redirectError, redirectInput, soloCommand); if (this.Command.Context.CurrentPipelineStopping) { throw new PipelineStoppedException(); } Exception innerException = (Exception)null; try { if (!redirectOutput) { this.Command.Context.EngineHostInterface.NotifyBeginApplication(); } lock (this.sync) { if (this.stopped) { throw new PipelineStoppedException(); } try { this.nativeProcess = new Process(); this.nativeProcess.StartInfo = processStartInfo; this.nativeProcess.Start(); } catch (Win32Exception ex1) { string executable = NativeCommandProcessor.FindExecutable(processStartInfo.FileName); bool flag = true; if (!string.IsNullOrEmpty(executable)) { if (NativeCommandProcessor.IsConsoleApplication(executable)) { ConsoleVisibility.AllocateHiddenConsole(); } string arguments = processStartInfo.Arguments; string fileName = processStartInfo.FileName; processStartInfo.Arguments = "\"" + processStartInfo.FileName + "\" " + processStartInfo.Arguments; processStartInfo.FileName = executable; try { this.nativeProcess.Start(); flag = false; } catch (Win32Exception ex2) { processStartInfo.Arguments = arguments; processStartInfo.FileName = fileName; } } if (flag) { if (soloCommand && !processStartInfo.UseShellExecute) { processStartInfo.UseShellExecute = true; processStartInfo.RedirectStandardInput = false; processStartInfo.RedirectStandardOutput = false; processStartInfo.RedirectStandardError = false; this.nativeProcess.Start(); } else { throw; } } } } bool flag1; if (this.Command.MyInvocation.PipelinePosition < this.Command.MyInvocation.PipelineLength) { flag1 = false; } else { flag1 = true; if (!processStartInfo.UseShellExecute) { flag1 = NativeCommandProcessor.IsWindowsApplication(this.nativeProcess.StartInfo.FileName); } } try { if (processStartInfo.RedirectStandardInput) { NativeCommandIOFormat inputFormat = NativeCommandIOFormat.Text; if (this.isMiniShell) { inputFormat = ((MinishellParameterBinderController)this.NativeParameterBinderController).InputFormat; } lock (this.sync) { if (!this.stopped) { this.inputWriter.Start(this.nativeProcess, inputFormat); } } } if (!flag1) { if (!processStartInfo.RedirectStandardOutput) { if (!processStartInfo.RedirectStandardError) { goto label_54; } } lock (this.sync) { if (!this.stopped) { this.outputReader = new ProcessOutputReader(this.nativeProcess, this.Path, redirectOutput, redirectError); this.outputReader.Start(); } } if (this.outputReader != null) { this.ProcessOutputHelper(); } } } catch (Exception ex) { NativeCommandProcessor.KillProcess(this.nativeProcess); throw; } finally { if (!flag1) { this.nativeProcess.WaitForExit(); this.inputWriter.Done(); if (this.outputReader != null) { this.outputReader.Done(); } this.Command.Context.SetVariable("global:LASTEXITCODE", (object)this.nativeProcess.ExitCode); if (this.nativeProcess.ExitCode != 0) { this.commandRuntime.PipelineProcessor.ExecutionFailed = true; } } } } catch (Win32Exception ex) { innerException = (Exception)ex; } catch (PipelineStoppedException ex) { throw; } catch (Exception ex) { CommandProcessorBase.CheckForSevereException(ex); innerException = ex; } finally { if (!redirectOutput) { this.Command.Context.EngineHostInterface.NotifyEndApplication(); } this.CleanUp(); } label_54: if (innerException != null) { string message = ResourceManagerCache.FormatResourceString("Parser", "ProgramFailedToExecute", (object)this.NativeCommandName, (object)innerException.Message, (object)this.Command.MyInvocation.PositionMessage); if (message == null) { message = StringUtil.Format("Program '{0}' failed to execute: {1}{2}", (object)this.NativeCommandName, (object)innerException.Message, (object)this.Command.MyInvocation.PositionMessage); } ApplicationFailedException applicationFailedException = new ApplicationFailedException(message, innerException); NativeCommandProcessor.tracer.TraceException((Exception)applicationFailedException); throw applicationFailedException; } }