/// <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 not respond. exceptionOccurred = e; } if (exceptionOccurred != null) { driver.SetState(PSInvocationState.Failed, exceptionOccurred); } }
/// <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); } }