public override Collection <PSObject> Invoke(IEnumerable input) { // TODO: run the pipeline on another thread and wait for the completion // TODO: nested pipelines: make sure we are running in the same thread as another pipeline, because // nested pipelines aren't allowed to run in their own thread. This ensures that there is a "parent" pipeline Input.Write(input, true); // in a pipeline, the first command enters *always* the ProcessRecord phase, the following commands only // if the previous command generated output. To make sure the first command enters that phase, add null // if nothing else is in the input stream if (_inputStream.Count == 0) { Input.Write(null); } string errorId = "BuildingPipelineProcessorFailed"; ExecutionContext context = _runspace.ExecutionContext.Clone(); RerouteExecutionContext(context); try { if (!_pipelineStateInfo.State.Equals(PipelineState.NotStarted)) { throw new InvalidPipelineStateException("Pipeline cannot be started", _pipelineStateInfo.State, PipelineState.NotStarted); } var pipelineProcessor = BuildPipelineProcessor(context); _runspace.AddRunningPipeline(this); SetPipelineState(PipelineState.Running); errorId = "TerminatingError"; pipelineProcessor.Execute(context); SetPipelineState(PipelineState.Completed); } catch (ExitException ex) { // Toplevel pipeline if (!IsNested) { _runspace.PSHost.SetShouldExit(ex.ExitCode); } else { // nested pipelines propagate the exit command throw; } } catch (Exception ex) { // in case of throw statement, parse error, or "ThrowTerminatingError" // just add to error variable and rethrow that thing var errorRecord = (ex is IContainsErrorRecord) ? ((IContainsErrorRecord)ex).ErrorRecord : new ErrorRecord(ex, errorId, ErrorCategory.InvalidOperation, null); context.AddToErrorVariable(errorRecord); context.SetVariable("global:?", false); // last command was definitely not successfull throw; } _runspace.RemoveRunningPipeline(this); return(Output.NonBlockingRead()); }
public override Collection <PSObject> Invoke(IEnumerable input) { // TODO: run the pipeline on another thread and wait for the completion // TODO: nested pipelines: make sure we are running in the same thread as another pipeline, because // nested pipelines aren't allowed to run in their own thread. This ensures that there is a "parent" pipeline Input.Write(input, true); // in a pipeline, the first command enters *always* the ProcessRecord phase, the following commands only // if the previous command generated output. To make sure the first command enters that phase, add null // if nothing else is in the input stream if (_inputStream.Count == 0) { Input.Write(null); } ExecutionContext context = _runspace.ExecutionContext.Clone(); RerouteExecutionContext(context); try { if (!_pipelineStateInfo.State.Equals(PipelineState.NotStarted)) { throw new InvalidPipelineStateException("Pipeline cannot be started", _pipelineStateInfo.State, PipelineState.NotStarted); } var pipelineProcessor = BuildPipelineProcessor(context); _runspace.AddRunningPipeline(this); SetPipelineState(PipelineState.Running); pipelineProcessor.Execute(context); SetPipelineState(PipelineState.Completed); } catch (FlowControlException ex) { if (IsNested) { throw; // propagate to parent levels } if (ex is ExitException) { // exit code must be an int. otherwise it's 0 int exitCode = 0; LanguagePrimitives.TryConvertTo <int>(((ExitException)ex).Argument, out exitCode); _runspace.PSHost.SetShouldExit(exitCode); } // at this point we are in the toplevel pipeline and we got a "return", "break", or "continue". // The behavior for this is that the pipeline stops (that's why we're here), but nothing else } catch (Exception ex) { // in case of throw statement, parse error, or "ThrowTerminatingError" // just add to error variable, the error stream and rethrow that thing context.AddToErrorVariable(ex); context.SetSuccessVariable(false); // last command was definitely not successfull throw; } _runspace.RemoveRunningPipeline(this); return(Output.NonBlockingRead()); }