Example #1
0
        /// <summary>
        /// Default constructor for creating ServerSteppablePipelineDriver...Used by server to concurrently
        /// run 2 pipelines.
        /// </summary>
        /// <param name="powershell">Decoded powershell object.</param>
        /// <param name="noInput">Whether there is input for this powershell.</param>
        /// <param name="clientPowerShellId">The client powershell id.</param>
        /// <param name="clientRunspacePoolId">The client runspacepool id.</param>
        /// <param name="runspacePoolDriver">runspace pool driver
        /// which is creating this powershell driver</param>
        /// <param name="apartmentState">Apartment state for this powershell.</param>
        /// <param name="hostInfo">host info using which the host for
        /// this powershell will be constructed</param>
        /// <param name="streamOptions">Serialization options for the streams in this powershell.</param>
        /// <param name="addToHistory">
        /// true if the command is to be added to history list of the runspace. false, otherwise.
        /// </param>
        /// <param name="rsToUse">
        /// If not null, this Runspace will be used to invoke Powershell.
        /// If null, the RunspacePool pointed by <paramref name="runspacePoolDriver"/> will be used.
        /// </param>
        /// <param name="eventSubscriber">
        /// Steppable pipeline event subscriber
        /// </param>
        /// <param name="powershellInput">Input collection of the PowerShell pipeline.</param>
        internal ServerSteppablePipelineDriver(PowerShell powershell, bool noInput, Guid clientPowerShellId,
                                               Guid clientRunspacePoolId, ServerRunspacePoolDriver runspacePoolDriver,
                                               ApartmentState apartmentState, HostInfo hostInfo, RemoteStreamOptions streamOptions,
                                               bool addToHistory, Runspace rsToUse, ServerSteppablePipelineSubscriber eventSubscriber, PSDataCollection <object> powershellInput)
#endif
        {
            LocalPowerShell     = powershell;
            InstanceId          = clientPowerShellId;
            RunspacePoolId      = clientRunspacePoolId;
            RemoteStreamOptions = streamOptions;
#if !CORECLR // No ApartmentState In CoreCLR
            this.apartmentState = apartmentState;
#endif
            NoInput          = noInput;
            _addToHistory    = addToHistory;
            _eventSubscriber = eventSubscriber;
            _powershellInput = powershellInput;

            Input                      = new PSDataCollection <object>();
            InputEnumerator            = Input.GetEnumerator();
            Input.ReleaseOnEnumeration = true;

            DataStructureHandler = runspacePoolDriver.DataStructureHandler.CreatePowerShellDataStructureHandler(clientPowerShellId, clientRunspacePoolId, RemoteStreamOptions, null);
            RemoteHost           = DataStructureHandler.GetHostAssociatedWithPowerShell(hostInfo, runspacePoolDriver.ServerRemoteHost);

            // subscribe to various data structure handler events
            DataStructureHandler.InputEndReceived       += new EventHandler(HandleInputEndReceived);
            DataStructureHandler.InputReceived          += new EventHandler <RemoteDataEventArgs <object> >(HandleInputReceived);
            DataStructureHandler.StopPowerShellReceived += new EventHandler(HandleStopReceived);
            DataStructureHandler.HostResponseReceived   +=
                new EventHandler <RemoteDataEventArgs <RemoteHostResponse> >(HandleHostResponseReceived);
            DataStructureHandler.OnSessionConnected += new EventHandler(HandleSessionConnected);

            if (rsToUse == null)
            {
                throw PSTraceSource.NewInvalidOperationException(RemotingErrorIdStrings.NestedPipelineMissingRunspace);
            }

            // else, set the runspace pool and invoke this powershell
            LocalPowerShell.Runspace = rsToUse;
            eventSubscriber.SubscribeEvents(this);

            PipelineState = PSInvocationState.NotStarted;
        }
        /// <summary>
        /// Changes state and sends message to the client as needed.
        /// </summary>
        /// <param name="newState"></param>
        /// <param name="reason"></param>
        internal void SetState(PSInvocationState newState, Exception reason)
        {
            PSInvocationState copyState = PSInvocationState.NotStarted;
            bool shouldRaiseEvents      = false;

            lock (SyncObject)
            {
                switch (PipelineState)
                {
                case PSInvocationState.NotStarted:
                {
                    switch (newState)
                    {
                    case PSInvocationState.Running:
                    case PSInvocationState.Stopping:
                    case PSInvocationState.Completed:
                    case PSInvocationState.Stopped:
                    case PSInvocationState.Failed:
                        copyState = newState;
                        // NotStarted -> Running..we dont send
                        // state back to client.
                        break;
                    }
                }

                break;

                case PSInvocationState.Running:
                {
                    switch (newState)
                    {
                    case PSInvocationState.NotStarted:
                        throw new InvalidOperationException();

                    case PSInvocationState.Running:
                        break;

                    case PSInvocationState.Stopping:
                        copyState = newState;
                        break;

                    case PSInvocationState.Completed:
                    case PSInvocationState.Stopped:
                    case PSInvocationState.Failed:
                        copyState         = newState;
                        shouldRaiseEvents = true;
                        break;
                    }
                }

                break;

                case PSInvocationState.Stopping:
                {
                    switch (newState)
                    {
                    case PSInvocationState.Completed:
                    case PSInvocationState.Failed:
                        copyState         = PSInvocationState.Stopped;
                        shouldRaiseEvents = true;
                        break;

                    case PSInvocationState.Stopped:
                        copyState         = newState;
                        shouldRaiseEvents = true;
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }

                break;

                case PSInvocationState.Stopped:
                case PSInvocationState.Completed:
                case PSInvocationState.Failed:
                    break;
                }

                PipelineState = copyState;
            }

            if (shouldRaiseEvents)
            {
                // send the state change notification to the client
                DataStructureHandler.SendStateChangedInformationToClient(
                    new PSInvocationStateInfo(copyState, reason));
            }

            if (PipelineState == PSInvocationState.Completed ||
                PipelineState == PSInvocationState.Stopped ||
                PipelineState == PSInvocationState.Failed)
            {
                // Remove itself from the runspace pool
                DataStructureHandler.RaiseRemoveAssociationEvent();
            }
        }
Example #3
0
        /// <summary>
        /// Default constructor for creating ServerPowerShellDrivers
        /// </summary>
        /// <param name="powershell">decoded powershell object</param>
        /// <param name="extraPowerShell">extra pipeline to be run after <paramref name="powershell"/> completes</param>
        /// <param name="noInput">whether there is input for this powershell</param>
        /// <param name="clientPowerShellId">the client powershell id</param>
        /// <param name="clientRunspacePoolId">the client runspacepool id</param>
        /// <param name="runspacePoolDriver">runspace pool driver
        /// which is creating this powershell driver</param>
        /// <param name="apartmentState">apartment state for this powershell</param>
        /// <param name="hostInfo">host info using which the host for
        /// this powershell will be constructed</param>
        /// <param name="streamOptions">serialization options for the streams in this powershell</param>
        /// <param name="addToHistory">
        /// true if the command is to be added to history list of the runspace. false, otherwise.
        /// </param>
        /// <param name="rsToUse">
        /// If not null, this Runspace will be used to invoke Powershell.
        /// If null, the RunspacePool pointed by <paramref name="runspacePoolDriver"/> will be used.
        /// </param>
        /// <param name="output">
        /// If not null, this is used as another source of output sent to the client.
        /// </param>
        internal ServerPowerShellDriver(PowerShell powershell, PowerShell extraPowerShell, bool noInput, Guid clientPowerShellId,
                                        Guid clientRunspacePoolId, ServerRunspacePoolDriver runspacePoolDriver,
                                        ApartmentState apartmentState, HostInfo hostInfo, RemoteStreamOptions streamOptions,
                                        bool addToHistory, Runspace rsToUse, PSDataCollection <PSObject> output)
#endif
        {
            InstanceId          = clientPowerShellId;
            RunspacePoolId      = clientRunspacePoolId;
            RemoteStreamOptions = streamOptions;
#if !CORECLR // No ApartmentState In CoreCLR
            this.apartmentState = apartmentState;
#endif
            LocalPowerShell        = powershell;
            _extraPowerShell       = extraPowerShell;
            _localPowerShellOutput = new PSDataCollection <PSObject>();
            _noInput         = noInput;
            _addToHistory    = addToHistory;
            _psDriverInvoker = runspacePoolDriver;

            DataStructureHandler = runspacePoolDriver.DataStructureHandler.CreatePowerShellDataStructureHandler(clientPowerShellId, clientRunspacePoolId, RemoteStreamOptions, LocalPowerShell);
            _remoteHost          = DataStructureHandler.GetHostAssociatedWithPowerShell(hostInfo, runspacePoolDriver.ServerRemoteHost);

            if (!noInput)
            {
                InputCollection = new PSDataCollection <object>();
                InputCollection.ReleaseOnEnumeration = true;
                InputCollection.IdleEvent           += new EventHandler <EventArgs>(HandleIdleEvent);
            }

            RegisterPipelineOutputEventHandlers(_localPowerShellOutput);

            if (LocalPowerShell != null)
            {
                RegisterPowerShellEventHandlers(LocalPowerShell);
                _datasent[0] = false;
            }

            if (extraPowerShell != null)
            {
                RegisterPowerShellEventHandlers(extraPowerShell);
                _datasent[1] = false;
            }

            RegisterDataStructureHandlerEventHandlers(DataStructureHandler);

            // set the runspace pool and invoke this powershell
            if (rsToUse != null)
            {
                LocalPowerShell.Runspace = rsToUse;
                if (extraPowerShell != null)
                {
                    extraPowerShell.Runspace = rsToUse;
                }
            }
            else
            {
                LocalPowerShell.RunspacePool = runspacePoolDriver.RunspacePool;
                if (extraPowerShell != null)
                {
                    extraPowerShell.RunspacePool = runspacePoolDriver.RunspacePool;
                }
            }

            if (output != null)
            {
                output.DataAdded += (sender, args) =>
                {
                    if (_localPowerShellOutput.IsOpen)
                    {
                        var items = output.ReadAll();
                        foreach (var item in items)
                        {
                            _localPowerShellOutput.Add(item);
                        }
                    }
                };
            }
        }