private void HandleStartEvent(object sender, PSEventArgs args) { ServerSteppablePipelineDriverEventArg sourceEventArgs = args.SourceEventArgs as ServerSteppablePipelineDriverEventArg; ServerSteppablePipelineDriver steppableDriver = sourceEventArgs.SteppableDriver; Exception reason = null; try { using (ExecutionContextForStepping.PrepareExecutionContext(steppableDriver.LocalPowerShell.GetContextFromTLS(), steppableDriver.LocalPowerShell.InformationalBuffers, steppableDriver.RemoteHost)) { steppableDriver.SteppablePipeline = steppableDriver.LocalPowerShell.GetSteppablePipeline(); steppableDriver.SteppablePipeline.Begin(!steppableDriver.NoInput); } if (steppableDriver.NoInput) { steppableDriver.HandleInputEndReceived(this, EventArgs.Empty); } } catch (Exception exception2) { reason = exception2; } if (reason != null) { steppableDriver.SetState(PSInvocationState.Failed, reason); } }
internal void FireStartSteppablePipeline(ServerSteppablePipelineDriver driver) { lock (this.syncObject) { if (this.eventManager != null) { this.eventManager.GenerateEvent(this.startSubscriber.SourceIdentifier, this, new object[] { new ServerSteppablePipelineDriverEventArg(driver) }, null, true, false); } } }
internal void FireStartSteppablePipeline(ServerSteppablePipelineDriver driver) { lock (this.syncObject) { if (this.eventManager != null) { this.eventManager.GenerateEvent(this.startSubscriber.SourceIdentifier, this, new object[] { new ServerSteppablePipelineDriverEventArg(driver) }, null, true, false); } } }
/// <summary> /// Fires the process record event /// </summary> /// <param name="driver">steppable pipeline driver</param> internal void FireHandleProcessRecord(ServerSteppablePipelineDriver driver) { lock (_syncObject) { if (_eventManager != null) { _eventManager.GenerateEvent(_processSubscriber.SourceIdentifier, this, new object[1] { new ServerSteppablePipelineDriverEventArg(driver) }, null, true, false); } } }
internal void SubscribeEvents(ServerSteppablePipelineDriver driver) { lock (this.syncObject) { if (!this.initialized) { this.eventManager = driver.LocalPowerShell.Runspace.Events as PSLocalEventManager; if (this.eventManager != null) { this.startSubscriber = this.eventManager.SubscribeEvent(this, "StartSteppablePipeline", Guid.NewGuid().ToString(), null, new PSEventReceivedEventHandler(this.HandleStartEvent), true, false, true, 0); this.processSubscriber = this.eventManager.SubscribeEvent(this, "RunProcessRecord", Guid.NewGuid().ToString(), null, new PSEventReceivedEventHandler(this.HandleProcessRecord), true, false, true, 0); } this.initialized = true; } } }
internal void SubscribeEvents(ServerSteppablePipelineDriver driver) { lock (_syncObject) { if (!_initialized) { _eventManager = (object)driver.LocalPowerShell.Runspace.Events as PSLocalEventManager; if (_eventManager != null) { _startSubscriber = _eventManager.SubscribeEvent(this, "StartSteppablePipeline", Guid.NewGuid().ToString(), null, new PSEventReceivedEventHandler(this.HandleStartEvent), true, false, true); _processSubscriber = _eventManager.SubscribeEvent(this, "RunProcessRecord", Guid.NewGuid().ToString(), null, new PSEventReceivedEventHandler(this.HandleProcessRecord), true, false, true); } _initialized = true; } } }
/// <summary> /// Handles the start pipeline event, this is called by the event manager /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void HandleStartEvent(object sender, PSEventArgs args) { ServerSteppablePipelineDriverEventArg driverArg = (object)args.SourceEventArgs as ServerSteppablePipelineDriverEventArg; ServerSteppablePipelineDriver driver = driverArg.SteppableDriver; Exception exceptionOccurred = null; try { using (ExecutionContextForStepping ctxt = ExecutionContextForStepping.PrepareExecutionContext( driver.LocalPowerShell.GetContextFromTLS(), driver.LocalPowerShell.InformationalBuffers, driver.RemoteHost)) { driver.SteppablePipeline = driver.LocalPowerShell.GetSteppablePipeline(); driver.SteppablePipeline.Begin(!driver.NoInput); } if (driver.NoInput) { driver.HandleInputEndReceived(this, EventArgs.Empty); } } catch (Exception e) { // We need to catch this so that we can set the pipeline execution; // state to "failed" and send the exception as an error to the user. // Otherwise, the event manager will swallow this exception and // cause the client to hang. exceptionOccurred = e; } if (exceptionOccurred != null) { driver.SetState(PSInvocationState.Failed, exceptionOccurred); } }
internal ServerSteppablePipelineDriverEventArg(ServerSteppablePipelineDriver driver) { this.SteppableDriver = driver; }
/// <summary> /// Handles process record event /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void HandleProcessRecord(object sender, PSEventArgs args) { ServerSteppablePipelineDriverEventArg driverArg = (object)args.SourceEventArgs as ServerSteppablePipelineDriverEventArg; ServerSteppablePipelineDriver driver = driverArg.SteppableDriver; lock (driver.SyncObject) { // Make sure start event handler was called if (driver.SteppablePipeline == null) { return; } // make sure only one thread does the processing if (driver.ProcessingInput) { return; } driver.ProcessingInput = true; driver.Pulsed = false; } bool shouldDoComplete = false; Exception exceptionOccurred = null; try { using (ExecutionContextForStepping ctxt = ExecutionContextForStepping.PrepareExecutionContext( driver.LocalPowerShell.GetContextFromTLS(), driver.LocalPowerShell.InformationalBuffers, driver.RemoteHost)) { bool isProcessCalled = false; while (true) { if (driver.PipelineState != PSInvocationState.Running) { driver.SetState(driver.PipelineState, null); return; } if (!driver.InputEnumerator.MoveNext()) { shouldDoComplete = true; if (!driver.NoInput || isProcessCalled) { // if there is noInput then we // need to call process atleast once break; } } isProcessCalled = true; Array output; if (driver.NoInput) { output = driver.SteppablePipeline.Process(); } else { output = driver.SteppablePipeline.Process(driver.InputEnumerator.Current); } foreach (object o in output) { if (driver.PipelineState != PSInvocationState.Running) { driver.SetState(driver.PipelineState, null); return; } // send the output data to the client driver.DataStructureHandler.SendOutputDataToClient(PSObject.AsPSObject(o)); } lock (driver.SyncObject) { driver.TotalObjectsProcessed++; if (driver.TotalObjectsProcessed >= driver.Input.Count) { break; } } } } } catch (Exception e) { exceptionOccurred = e; } finally { lock (driver.SyncObject) { driver.ProcessingInput = false; driver.CheckAndPulseForProcessing(false); } // Check if should perform stop if (driver.PipelineState == PSInvocationState.Stopping) { driver.PerformStop(); } } if (shouldDoComplete) { try { using (ExecutionContextForStepping ctxt = ExecutionContextForStepping.PrepareExecutionContext( driver.LocalPowerShell.GetContextFromTLS(), driver.LocalPowerShell.InformationalBuffers, driver.RemoteHost)) { Array output = driver.SteppablePipeline.End(); foreach (object o in output) { if (driver.PipelineState != PSInvocationState.Running) { driver.SetState(driver.PipelineState, null); return; } // send the output data to the client driver.DataStructureHandler.SendOutputDataToClient(PSObject.AsPSObject(o)); } driver.SetState(PSInvocationState.Completed, null); return; } } catch (Exception e) { exceptionOccurred = e; } finally { // Check if should perform stop if (driver.PipelineState == PSInvocationState.Stopping) { driver.PerformStop(); } } } if (exceptionOccurred != null) { driver.SetState(PSInvocationState.Failed, exceptionOccurred); } }
/// <summary> /// Handle the invocation of powershell /// </summary> /// <param name="sender">sender of this event, unused</param> /// <param name="eventArgs">arguments describing this event</param> private void HandleCreateAndInvokePowerShell(object sender, RemoteDataEventArgs<RemoteDataObject<PSObject>> eventArgs) { RemoteDataObject<PSObject> data = eventArgs.Data; // it is sufficient to just construct the powershell // driver, the local powershell on server side is // invoked from within the driver HostInfo hostInfo = RemotingDecoder.GetHostInfo(data.Data); #if !CORECLR // No ApartmentState In CoreCLR ApartmentState apartmentState = RemotingDecoder.GetApartmentState(data.Data); #endif RemoteStreamOptions streamOptions = RemotingDecoder.GetRemoteStreamOptions(data.Data); PowerShell powershell = RemotingDecoder.GetPowerShell(data.Data); bool noInput = RemotingDecoder.GetNoInput(data.Data); bool addToHistory = RemotingDecoder.GetAddToHistory(data.Data); bool isNested = false; // The server would've dropped the protocol version of an older client was connecting if (_serverCapability.ProtocolVersion >= RemotingConstants.ProtocolVersionWin8RTM) { isNested = RemotingDecoder.GetIsNested(data.Data); } // Perform pre-processing of command for over the wire debugging commands. if (_serverRemoteDebugger != null) { DebuggerCommandArgument commandArgument; bool terminateImmediate = false; var result = PreProcessDebuggerCommand(powershell.Commands, _serverRemoteDebugger.IsActive, _serverRemoteDebugger.IsRemote, out commandArgument); switch (result) { case PreProcessCommandResult.SetDebuggerAction: // Run this directly on the debugger and terminate the remote command. _serverRemoteDebugger.SetDebuggerAction(commandArgument.ResumeAction.Value); terminateImmediate = true; break; case PreProcessCommandResult.SetDebugMode: // Set debug mode directly and terminate remote command. _serverRemoteDebugger.SetDebugMode(commandArgument.Mode.Value); terminateImmediate = true; break; case PreProcessCommandResult.SetDebuggerStepMode: // Enable debugger and set to step action, then terminate remote command. _serverRemoteDebugger.SetDebuggerStepMode(commandArgument.DebuggerStepEnabled.Value); terminateImmediate = true; break; case PreProcessCommandResult.SetPreserveUnhandledBreakpointMode: _serverRemoteDebugger.UnhandledBreakpointMode = commandArgument.UnhandledBreakpointMode.Value; terminateImmediate = true; break; case PreProcessCommandResult.ValidNotProcessed: terminateImmediate = true; break; } // If we don't want to run or queue a command to run in the server session then // terminate the command here by making it a No Op. if (terminateImmediate) { ServerPowerShellDriver noOpDriver = new ServerPowerShellDriver( powershell, null, noInput, data.PowerShellId, data.RunspacePoolId, this, #if !CORECLR // No ApartmentState In CoreCLR apartmentState, #endif hostInfo, streamOptions, addToHistory, null); noOpDriver.RunNoOpCommand(); return; } } if (_remoteHost.IsRunspacePushed) { // If we have a pushed runspace then execute there. // Ensure debugger is enabled to the original mode it was set to. if (_serverRemoteDebugger != null) { _serverRemoteDebugger.CheckDebuggerState(); } StartPowerShellCommandOnPushedRunspace( powershell, null, data.PowerShellId, data.RunspacePoolId, hostInfo, streamOptions, noInput, addToHistory); return; } else if (isNested) { if (RunspacePool.GetMaxRunspaces() == 1) { if (_driverNestedInvoker != null && _driverNestedInvoker.IsActive) { if (_driverNestedInvoker.IsAvailable == false) { // A nested command is already running. throw new PSInvalidOperationException( StringUtil.Format(RemotingErrorIdStrings.CannotInvokeNestedCommandNestedCommandRunning)); } // Handle as nested pipeline invocation. powershell.SetIsNested(true); // Always invoke PowerShell commands on pipeline worker thread // for single runspace case, to support nested invocation requests (debugging scenario). ServerPowerShellDriver srdriver = new ServerPowerShellDriver( powershell, null, noInput, data.PowerShellId, data.RunspacePoolId, this, #if !CORECLR // No ApartmentState In CoreCLR apartmentState, #endif hostInfo, streamOptions, addToHistory, _rsToUseForSteppablePipeline); _inputCollection = srdriver.InputCollection; _driverNestedInvoker.InvokeDriverAsync(srdriver); return; } else if (_serverRemoteDebugger != null && _serverRemoteDebugger.InBreakpoint && _serverRemoteDebugger.IsPushed) { _serverRemoteDebugger.StartPowerShellCommand( powershell, data.PowerShellId, data.RunspacePoolId, this, #if !CORECLR // No ApartmentState In CoreCLR apartmentState, #endif _remoteHost, hostInfo, streamOptions, addToHistory); return; } else if (powershell.Commands.Commands.Count == 1 && !powershell.Commands.Commands[0].IsScript && ((powershell.Commands.Commands[0].CommandText.IndexOf("Get-PSDebuggerStopArgs", StringComparison.OrdinalIgnoreCase) != -1) || (powershell.Commands.Commands[0].CommandText.IndexOf("Set-PSDebuggerAction", StringComparison.OrdinalIgnoreCase) != -1))) { // We do not want to invoke debugger commands in the steppable pipeline. // Consider adding IsSteppable message to PSRP to handle this. // This will be caught on the client. throw new PSInvalidOperationException(); } ServerPowerShellDataStructureHandler psHandler = DataStructureHandler.GetPowerShellDataStructureHandler(); if (psHandler != null) { // Have steppable invocation request. powershell.SetIsNested(false); // Execute command concurrently ServerSteppablePipelineDriver spDriver = new ServerSteppablePipelineDriver( powershell, noInput, data.PowerShellId, data.RunspacePoolId, this, #if !CORECLR // No ApartmentState In CoreCLR apartmentState, #endif hostInfo, streamOptions, addToHistory, _rsToUseForSteppablePipeline, _eventSubscriber, _inputCollection); spDriver.Start(); return; } } // Allow command to run as non-nested and non-stepping. powershell.SetIsNested(false); } // Invoke command normally. Ensure debugger is enabled to the // original mode it was set to. if (_serverRemoteDebugger != null) { _serverRemoteDebugger.CheckDebuggerState(); } // Invoke PowerShell on driver runspace pool. ServerPowerShellDriver driver = new ServerPowerShellDriver( powershell, null, noInput, data.PowerShellId, data.RunspacePoolId, this, #if !CORECLR // No ApartmentState In CoreCLR apartmentState, #endif hostInfo, streamOptions, addToHistory, null); _inputCollection = driver.InputCollection; driver.Start(); }
internal ServerSteppablePipelineDriverEventArg(ServerSteppablePipelineDriver driver) { this.SteppableDriver = driver; }
private void HandleProcessRecord(object sender, PSEventArgs args) { ServerSteppablePipelineDriverEventArg sourceEventArgs = args.SourceEventArgs as ServerSteppablePipelineDriverEventArg; ServerSteppablePipelineDriver steppableDriver = sourceEventArgs.SteppableDriver; lock (steppableDriver.SyncObject) { if ((steppableDriver.SteppablePipeline == null) || steppableDriver.ProcessingInput) { return; } steppableDriver.ProcessingInput = true; steppableDriver.Pulsed = false; } bool flag = false; Exception reason = null; try { using (ExecutionContextForStepping.PrepareExecutionContext(steppableDriver.LocalPowerShell.GetContextFromTLS(), steppableDriver.LocalPowerShell.InformationalBuffers, steppableDriver.RemoteHost)) { bool flag2 = false; Label_0086: if (steppableDriver.PipelineState != PSInvocationState.Running) { steppableDriver.SetState(steppableDriver.PipelineState, null); return; } if (!steppableDriver.InputEnumerator.MoveNext()) { flag = true; if (!steppableDriver.NoInput || flag2) { goto Label_0203; } } flag2 = true; Array array = new int[0]; if (steppableDriver.NoInput) { array = steppableDriver.SteppablePipeline.Process(); } else { array = steppableDriver.SteppablePipeline.Process(steppableDriver.InputEnumerator.Current); } foreach (object obj2 in array) { if (steppableDriver.PipelineState != PSInvocationState.Running) { steppableDriver.SetState(steppableDriver.PipelineState, null); return; } steppableDriver.DataStructureHandler.SendOutputDataToClient(PSObject.AsPSObject(obj2)); } lock (steppableDriver.SyncObject) { steppableDriver.TotalObjectsProcessed++; if (steppableDriver.TotalObjectsProcessed < steppableDriver.Input.Count) { goto Label_0086; } } } } catch (Exception exception2) { CommandProcessorBase.CheckForSevereException(exception2); reason = exception2; } finally { lock (steppableDriver.SyncObject) { steppableDriver.ProcessingInput = false; steppableDriver.CheckAndPulseForProcessing(false); } if (steppableDriver.PipelineState == PSInvocationState.Stopping) { steppableDriver.PerformStop(); } } Label_0203: if (flag) { try { using (ExecutionContextForStepping.PrepareExecutionContext(steppableDriver.LocalPowerShell.GetContextFromTLS(), steppableDriver.LocalPowerShell.InformationalBuffers, steppableDriver.RemoteHost)) { foreach (object obj3 in steppableDriver.SteppablePipeline.End()) { if (steppableDriver.PipelineState != PSInvocationState.Running) { steppableDriver.SetState(steppableDriver.PipelineState, null); return; } steppableDriver.DataStructureHandler.SendOutputDataToClient(PSObject.AsPSObject(obj3)); } steppableDriver.SetState(PSInvocationState.Completed, null); return; } } catch (Exception exception3) { CommandProcessorBase.CheckForSevereException(exception3); reason = exception3; } finally { if (steppableDriver.PipelineState == PSInvocationState.Stopping) { steppableDriver.PerformStop(); } } } if (reason != null) { steppableDriver.SetState(PSInvocationState.Failed, reason); } }
/// <summary> /// Fires the process record event /// </summary> /// <param name="driver">steppable pipeline driver</param> internal void FireHandleProcessRecord(ServerSteppablePipelineDriver driver) { lock (_syncObject) { if (_eventManager != null) { _eventManager.GenerateEvent(_processSubscriber.SourceIdentifier, this, new object[1] { new ServerSteppablePipelineDriverEventArg(driver) }, null, true, false); } } }