Ejemplo n.º 1
0
        /// <summary>
        /// Invoke the pipeline asynchronously with input.
        /// </summary>
        /// <param name="input">input to provide to pipeline. Input is
        /// used only for synchronous execution</param>
        /// <param name="syncCall">True if this method is called from
        /// synchronous invoke else false</param>
        /// <remarks>
        /// Results are returned through the <see cref="Pipeline.Output"/> reader.
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        /// No command is added to pipeline
        /// </exception>
        /// <exception cref="InvalidPipelineStateException">
        /// PipelineState is not NotStarted.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// 1) A pipeline is already executing. Pipeline cannot execute
        /// concurrently.
        /// 2) InvokeAsync is called on nested pipeline. Nested pipeline
        /// cannot be executed Asynchronously.
        /// 3) Attempt is made to invoke a nested pipeline directly. Nested
        /// pipeline must be invoked from a running pipeline.
        /// </exception>
        /// <exception cref="InvalidRunspaceStateException">
        /// RunspaceState is not Open
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        /// Pipeline already disposed
        /// </exception>
        private void CoreInvoke(IEnumerable input, bool syncCall)
        {
            lock (SyncRoot)
            {
                // NTRAID#Windows Out Of Band Releases-915851-2005/09/13
                if (_disposed)
                {
                    throw PSTraceSource.NewObjectDisposedException("pipeline");
                }

                if (Commands == null || Commands.Count == 0)
                {
                    throw PSTraceSource.NewInvalidOperationException(
                              RunspaceStrings.NoCommandInPipeline);
                }

                if (PipelineState != PipelineState.NotStarted)
                {
                    InvalidPipelineStateException e =
                        new InvalidPipelineStateException
                        (
                            StringUtil.Format(RunspaceStrings.PipelineReInvokeNotAllowed),
                            PipelineState,
                            PipelineState.NotStarted
                        );
                    throw e;
                }

                if (syncCall && !(InputStream is PSDataCollectionStream <PSObject> || InputStream is PSDataCollectionStream <object>))
                {
                    // Method is called from synchronous invoke.
                    if (input != null)
                    {
                        // TO-DO-Add a test make sure that ObjectDisposed
                        // exception is thrown
                        // Write input data in to inputStream and close the input
                        // pipe. If Input stream is already closed an
                        // ObjectDisposed exception will be thrown
                        foreach (object temp in input)
                        {
                            InputStream.Write(temp);
                        }
                    }

                    InputStream.Close();
                }

                SyncInvokeCall = syncCall;

                // Create event which will be signalled when pipeline execution
                // is completed/failed/stoped.
                // Note:Runspace.Close waits for all the running pipeline
                // to finish.  This Event must be created before pipeline is
                // added to list of running pipelines. This avoids the race condition
                // where Close is called after pipeline is added to list of
                // running pipeline but before event is created.
                PipelineFinishedEvent = new ManualResetEvent(false);

                // 1) Do the check to ensure that pipeline no other
                // pipeline is running.
                // 2) Runspace object maintains a list of pipelines in
                // execution. Add this pipeline to the list.
                RunspaceBase.DoConcurrentCheckAndAddToRunningPipelines(this, syncCall);

                // Note: Set PipelineState to Running only after adding pipeline to list
                // of pipelines in execution. AddForExecution checks that runspace is in
                // state where pipeline can be run.
                // StartPipelineExecution raises this event. See Windows Bug 1160481 for
                // more details.
                SetPipelineState(PipelineState.Running);
            }

            try
            {
                // Let the derived class start the pipeline execution.
                StartPipelineExecution();
            }
            catch (Exception exception)
            {
                // If we fail in any of the above three steps, set the correct states.
                RunspaceBase.RemoveFromRunningPipelineList(this);
                SetPipelineState(PipelineState.Failed, exception);

                // Note: we are not raising the events in this case. However this is
                // fine as user is getting the exception.
                throw;
            }
        }