private void ConnectSessionToHost(PSSession session, PSRemotingJob job = null) { RemoteRunspace runspace = session.Runspace as RemoteRunspace; if (job != null) { lock (this._syncObject) { this._job = job; } using (job) { Job job2 = job.ChildJobs[0]; job.ConnectJobs(); do { job2.Results.WaitHandle.WaitOne(); foreach (PSStreamObject obj2 in job2.ReadAll()) { if (obj2 != null) { obj2.WriteStreamObject(this, false); } } } while (!job.IsFinishedState(job.JobStateInfo.State)); } lock (this._syncObject) { this._job = null; } } else if (runspace.RemoteCommand != null) { lock (this._syncObject) { this._remotePipeline = (RemotePipeline) session.Runspace.CreateDisconnectedPipeline(); } using (this._remotePipeline) { this._remotePipeline.ConnectAsync(); runspace.RunspacePool.RemoteRunspacePoolInternal.ConnectCommands = null; while (!this._remotePipeline.Output.EndOfPipeline) { if (this._stopProcessing) { break; } this._remotePipeline.Output.WaitHandle.WaitOne(); while (this._remotePipeline.Output.Count > 0) { if (this._stopProcessing) { continue; } PSObject psObject = this._remotePipeline.Output.Read(); this.WriteRemoteObject(psObject, session); } } if (this._remotePipeline.Error.Count > 0) { while (!this._remotePipeline.Error.EndOfPipeline) { object obj4 = this._remotePipeline.Error.Read(); if (obj4 is Collection<ErrorRecord>) { Collection<ErrorRecord> collection = (Collection<ErrorRecord>) obj4; foreach (ErrorRecord record in collection) { base.WriteError(record); } } else if (obj4 is ErrorRecord) { base.WriteError((ErrorRecord) obj4); } } } this._remotePipeline.PipelineFinishedEvent.WaitOne(); if (this._remotePipeline.PipelineStateInfo.State == PipelineState.Failed) { string pipelineFailedWithoutReason; Exception reason = this._remotePipeline.PipelineStateInfo.Reason; if ((reason != null) && !string.IsNullOrEmpty(reason.Message)) { pipelineFailedWithoutReason = StringUtil.Format(RemotingErrorIdStrings.PipelineFailedWithReason, reason.Message); } else { pipelineFailedWithoutReason = RemotingErrorIdStrings.PipelineFailedWithoutReason; } ErrorRecord errorRecord = new ErrorRecord(new RuntimeException(pipelineFailedWithoutReason, reason), "ReceivePSSessionPipelineFailed", ErrorCategory.OperationStopped, this._remotePipeline); base.WriteError(errorRecord); } } lock (this._syncObject) { this._remotePipeline = null; } } }
/// <summary> /// Connects session, retrieves command output data and writes to host. /// </summary> /// <param name="session">PSSession object.</param> /// <param name="job">Job object associated with session.</param> private void ConnectSessionToHost(PSSession session, PSRemotingJob job = null) { RemoteRunspace remoteRunspace = session.Runspace as RemoteRunspace; Dbg.Assert(remoteRunspace != null, "PS sessions can only contain RemoteRunspace type."); if (job != null) { // If we have a job object associated with the session then this means // the user explicitly chose to connect and return data synchronously. // Reconnect the job object and stream data to host. lock (_syncObject) { _job = job; _stopPipelineReceive = new ManualResetEvent(false); } using (_stopPipelineReceive) using (job) { Job childJob = job.ChildJobs[0]; job.ConnectJobs(); if (CheckForDebugMode(session, true)) { return; } do { // Retrieve and display results from child job as they become // available. int index = WaitHandle.WaitAny(new WaitHandle[] { _stopPipelineReceive, childJob.Results.WaitHandle }); foreach (var result in childJob.ReadAll()) { if (result != null) { result.WriteStreamObject(this); } } if (index == 0) { WriteDebugStopWarning(); return; } } while (!job.IsFinishedState(job.JobStateInfo.State)); } lock (_syncObject) { _job = null; _stopPipelineReceive = null; } return; } // Otherwise this must be a new disconnected session object that has a running command // associated with it. if (remoteRunspace.RemoteCommand == null) { // There is no associated running command for this runspace, so we cannot proceed. // Check to see if session is in debug mode. CheckForDebugMode(session, false); return; } // Create a RemotePipeline object for this command and attempt to connect. lock (_syncObject) { _remotePipeline = (RemotePipeline)session.Runspace.CreateDisconnectedPipeline(); _stopPipelineReceive = new ManualResetEvent(false); } using (_stopPipelineReceive) { using (_remotePipeline) { // Connect to remote running command. ManualResetEvent pipelineConnectedEvent = new ManualResetEvent(false); using (pipelineConnectedEvent) { _remotePipeline.StateChanged += (sender, args) => { if (pipelineConnectedEvent != null && (args.PipelineStateInfo.State == PipelineState.Running || args.PipelineStateInfo.State == PipelineState.Stopped || args.PipelineStateInfo.State == PipelineState.Failed)) { pipelineConnectedEvent.Set(); } }; _remotePipeline.ConnectAsync(); pipelineConnectedEvent.WaitOne(); } pipelineConnectedEvent = null; if (CheckForDebugMode(session, true)) { return; } // Wait for remote command to complete, while writing any available data. while (!_remotePipeline.Output.EndOfPipeline) { if (_stopProcessing) { break; } int index = WaitHandle.WaitAny(new WaitHandle[] { _stopPipelineReceive, _remotePipeline.Output.WaitHandle }); if (index == 0) { WriteDebugStopWarning(); return; } while (_remotePipeline.Output.Count > 0) { if (_stopProcessing) { break; } PSObject psObject = _remotePipeline.Output.Read(); WriteRemoteObject(psObject, session); } } // Write pipeline object errors. if (_remotePipeline.Error.Count > 0) { while (!_remotePipeline.Error.EndOfPipeline) { object errorObj = _remotePipeline.Error.Read(); if (errorObj is Collection<ErrorRecord>) { Collection<ErrorRecord> errorCollection = (Collection<ErrorRecord>)errorObj; foreach (ErrorRecord errorRecord in errorCollection) { WriteError(errorRecord); } } else if (errorObj is ErrorRecord) { WriteError((ErrorRecord)errorObj); } else { Dbg.Assert(false, "Objects in pipeline Error collection must be ErrorRecord type."); } } } // Wait for pipeline to finish. int wIndex = WaitHandle.WaitAny(new WaitHandle[] { _stopPipelineReceive, _remotePipeline.PipelineFinishedEvent }); if (wIndex == 0) { WriteDebugStopWarning(); return; } // Set the runspace RemoteCommand to null. It is not needed anymore and it // allows the runspace to become available after pipeline completes. remoteRunspace.RunspacePool.RemoteRunspacePoolInternal.ConnectCommands = null; // Check for any terminating errors to report. if (_remotePipeline.PipelineStateInfo.State == PipelineState.Failed) { Exception reason = _remotePipeline.PipelineStateInfo.Reason; string msg; if (reason != null && !string.IsNullOrEmpty(reason.Message)) { msg = StringUtil.Format(RemotingErrorIdStrings.PipelineFailedWithReason, reason.Message); } else { msg = RemotingErrorIdStrings.PipelineFailedWithoutReason; } ErrorRecord errorRecord = new ErrorRecord(new RuntimeException(msg, reason), "ReceivePSSessionPipelineFailed", ErrorCategory.OperationStopped, _remotePipeline ); WriteError(errorRecord); } } } lock (_syncObject) { _remotePipeline = null; _stopPipelineReceive = null; } }