private static void OnRemoteCmdSendCompleted(IntPtr operationContext, int flags, IntPtr error, IntPtr shellOperationHandle, IntPtr commandOperationHandle, IntPtr operationHandle, IntPtr data) { tracer.WriteLine("SendComplete callback received"); long cmdContextId = 0; WSManClientCommandTransportManager cmdTM = null; if (!TryGetCmdTransportManager(operationContext, out cmdTM, out cmdContextId)) { // We dont have the command TM handle..just return. tracer.WriteLine("Unable to find a transport manager for the command context {0}.", cmdContextId); return; } cmdTM._isSendingInput = false; // do the logging for this send PSEtwLog.LogAnalyticInformational(PSEventId.WSManSendShellInputExCallbackReceived, PSOpcode.Connect, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, cmdTM.RunspacePoolInstanceId.ToString(), cmdTM.powershellInstanceId.ToString()); if ((!shellOperationHandle.Equals(cmdTM._wsManShellOperationHandle)) || (!commandOperationHandle.Equals(cmdTM._wsManCmdOperationHandle))) { tracer.WriteLine("SendShellInputEx callback: ShellOperationHandles are not the same as the Send is initiated with"); // WSMan returned data from a wrong shell..notify the caller // about the same. PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.CommandSendExFailed); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.CommandInputEx); cmdTM.ProcessWSManTransportError(eventargs); return; } // release the resources related to send cmdTM.ClearReceiveOrSendResources(flags, true); // if the transport manager is already closed..ignore the errors and return if (cmdTM.isClosed) { tracer.WriteLine("Client Command TM: Transport manager is closed. So returning"); if (cmdTM._isDisconnectPending) { cmdTM.RaiseReadyForDisconnect(); } return; } if (IntPtr.Zero != error) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); // Ignore Command aborted error. Command aborted is raised by WSMan to // notify command operation complete. PowerShell protocol has its own // way of notifying the same using state change events. if ((errorStruct.errorCode != 0) && (errorStruct.errorCode != 995)) { tracer.WriteLine("CmdSend callback: WSMan reported an error: {0}", errorStruct.errorDetail); TransportErrorOccuredEventArgs eventargs = WSManTransportManagerUtils.ConstructTransportErrorEventArgs( cmdTM._sessnTm.WSManAPIData.WSManAPIHandle, null, errorStruct, TransportMethodEnum.CommandInputEx, RemotingErrorIdStrings.CommandSendExCallBackError, new object[] { WSManTransportManagerUtils.ParseEscapeWSManErrorMessage(errorStruct.errorDetail) }); cmdTM.ProcessWSManTransportError(eventargs); return; } } // Send the next item, if available cmdTM.SendOneItem(); }
private static void OnRemoteCmdDataReceived(IntPtr operationContext, int flags, IntPtr error, IntPtr shellOperationHandle, IntPtr commandOperationHandle, IntPtr operationHandle, IntPtr data) { tracer.WriteLine("Remote Command DataReceived callback."); long cmdContextId = 0; WSManClientCommandTransportManager cmdTM = null; if (!TryGetCmdTransportManager(operationContext, out cmdTM, out cmdContextId)) { // We dont have the command TM handle..just return. tracer.WriteLine("Unable to find a transport manager for the given command context {0}.", cmdContextId); return; } if ((!shellOperationHandle.Equals(cmdTM._wsManShellOperationHandle)) || (!commandOperationHandle.Equals(cmdTM._wsManCmdOperationHandle))) { // WSMan returned data from a wrong shell..notify the caller // about the same. tracer.WriteLine("CmdReceive callback: ShellOperationHandles are not the same as the Receive is initiated with"); PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.CommandReceiveExFailed); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.ReceiveCommandOutputEx); cmdTM.ProcessWSManTransportError(eventargs); return; } // release the resources related to receive cmdTM.ClearReceiveOrSendResources(flags, false); // if the transport manager is already closed..ignore the errors and return if (cmdTM.isClosed) { tracer.WriteLine("Client Command TM: Transport manager is closed. So returning"); return; } if (IntPtr.Zero != error) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) { tracer.WriteLine("CmdReceive callback: WSMan reported an error: {0}", errorStruct.errorDetail); TransportErrorOccuredEventArgs eventargs = WSManTransportManagerUtils.ConstructTransportErrorEventArgs( cmdTM._sessnTm.WSManAPIData.WSManAPIHandle, null, errorStruct, TransportMethodEnum.ReceiveCommandOutputEx, RemotingErrorIdStrings.CommandReceiveExCallBackError, new object[] { errorStruct.errorDetail }); cmdTM.ProcessWSManTransportError(eventargs); return; } } if (flags == (int)WSManNativeApi.WSManCallbackFlags.WSMAN_FLAG_RECEIVE_DELAY_STREAM_REQUEST_PROCESSED) { cmdTM._isDisconnectedOnInvoke = true; cmdTM.RaiseDelayStreamProcessedEvent(); return; } WSManNativeApi.WSManReceiveDataResult dataReceived = WSManNativeApi.WSManReceiveDataResult.UnMarshal(data); if (null != dataReceived.data) { tracer.WriteLine("Cmd Received Data : {0}", dataReceived.data.Length); PSEtwLog.LogAnalyticInformational( PSEventId.WSManReceiveShellOutputExCallbackReceived, PSOpcode.Receive, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, cmdTM.RunspacePoolInstanceId.ToString(), cmdTM.powershellInstanceId.ToString(), dataReceived.data.Length.ToString(CultureInfo.InvariantCulture)); cmdTM.ProcessRawData(dataReceived.data, dataReceived.stream); } }
/// <summary> /// </summary> /// <exception cref="PSRemotingTransportException"> /// WSManConnectShellCommandEx failed. /// </exception> internal override void ConnectAsync() { Dbg.Assert(!isClosed, "object already disposed"); ReceivedDataCollection.PrepareForStreamConnect(); // Empty the serializedPipeline data that contains PowerShell command information created in the // constructor. We are connecting to an existing command on the server and don't want to send // information on a new command. serializedPipeline.Read(); // create cmdContextId _cmdContextId = GetNextCmdTMHandleId(); AddCmdTransportManager(_cmdContextId, this); // Create Callback _connectCmdCompleted = new WSManNativeApi.WSManShellAsync(new IntPtr(_cmdContextId), s_cmdConnectCallback); _reconnectCmdCompleted = new WSManNativeApi.WSManShellAsync(new IntPtr(_cmdContextId), s_cmdReconnectCallback); lock (syncObject) { if (isClosed) { // the transport is already closed..so no need to create a connection // anymore. return; } WSManNativeApi.WSManConnectShellCommandEx(_wsManShellOperationHandle, 0, PowershellInstanceId.ToString().ToUpperInvariant(), IntPtr.Zero, IntPtr.Zero, _connectCmdCompleted, ref _wsManCmdOperationHandle); } if (_wsManCmdOperationHandle == IntPtr.Zero) { PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.RunShellCommandExFailed); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.ConnectShellCommandEx); ProcessWSManTransportError(eventargs); return; } }
/// <summary> /// /// </summary> /// <exception cref="PSRemotingTransportException"> /// WSManRunShellCommandEx failed. /// </exception> internal override void CreateAsync() { byte[] cmdPart1 = serializedPipeline.ReadOrRegisterCallback(null); if (null != cmdPart1) { #region SHIM: Redirection code for command code send. bool sendContinue = true; if (s_commandCodeSendRedirect != null) { object[] arguments = new object[2] { null, cmdPart1 }; sendContinue = (bool)s_commandCodeSendRedirect.DynamicInvoke(arguments); cmdPart1 = (byte[])arguments[0]; } if (!sendContinue) return; #endregion WSManNativeApi.WSManCommandArgSet argSet = new WSManNativeApi.WSManCommandArgSet(cmdPart1); // create cmdContextId _cmdContextId = GetNextCmdTMHandleId(); AddCmdTransportManager(_cmdContextId, this); PSEtwLog.LogAnalyticInformational(PSEventId.WSManCreateCommand, PSOpcode.Connect, PSTask.CreateRunspace, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, RunspacePoolInstanceId.ToString(), powershellInstanceId.ToString()); _createCmdCompleted = new WSManNativeApi.WSManShellAsync(new IntPtr(_cmdContextId), s_cmdCreateCallback); _createCmdCompletedGCHandle = GCHandle.Alloc(_createCmdCompleted); _reconnectCmdCompleted = new WSManNativeApi.WSManShellAsync(new IntPtr(_cmdContextId), s_cmdReconnectCallback); using (argSet) { lock (syncObject) { if (!isClosed) { WSManNativeApi.WSManRunShellCommandEx(_wsManShellOperationHandle, 0, PowershellInstanceId.ToString().ToUpperInvariant(), // WSManRunsShellCommand doesn't accept empty string "". (_cmdLine == null || _cmdLine.Length == 0) ? " " : (_cmdLine.Length <= 256 ? _cmdLine : _cmdLine.Substring(0, 255)), argSet, IntPtr.Zero, _createCmdCompleted, ref _wsManCmdOperationHandle); tracer.WriteLine("Started cmd with command context : {0} Operation context: {1}", _cmdContextId, _wsManCmdOperationHandle); } } } } if (_wsManCmdOperationHandle == IntPtr.Zero) { PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.RunShellCommandExFailed); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.RunShellCommandEx); ProcessWSManTransportError(eventargs); return; } }
private static void OnRemoteSessionSendCompleted(IntPtr operationContext, int flags, IntPtr error, IntPtr shellOperationHandle, IntPtr commandOperationHandle, IntPtr operationHandle, IntPtr data) { tracer.WriteLine("Client Session TM: SendComplete callback received"); long sessionTMHandle = 0; WSManClientSessionTransportManager sessionTM = null; if (!TryGetSessionTransportManager(operationContext, out sessionTM, out sessionTMHandle)) { // We dont have the session TM handle..just return. tracer.WriteLine("Unable to find a transport manager for context {0}.", sessionTMHandle); return; } // do the logging for this send PSEtwLog.LogAnalyticInformational(PSEventId.WSManSendShellInputExCallbackReceived, PSOpcode.Connect, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, sessionTM.RunspacePoolInstanceId.ToString(), Guid.Empty.ToString()); if (!shellOperationHandle.Equals(sessionTM._wsManShellOperationHandle)) { // WSMan returned data from a wrong shell..notify the caller // about the same. PSRemotingTransportException e = new PSRemotingTransportException( PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.SendExFailed, sessionTM.ConnectionInfo.ComputerName)); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.SendShellInputEx); sessionTM.ProcessWSManTransportError(eventargs); return; } sessionTM.ClearReceiveOrSendResources(flags, true); // if the session is already closed ignore the errors and return. if (sessionTM.isClosed) { tracer.WriteLine("Client Session TM: Transport manager is closed. So returning"); return; } if (IntPtr.Zero != error) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); // Ignore operation aborted error. operation aborted is raised by WSMan to // notify operation complete. PowerShell protocol has its own // way of notifying the same using state change events. if ((errorStruct.errorCode != 0) && (errorStruct.errorCode != 995)) { tracer.WriteLine("Got error with error code {0}. Message {1}", errorStruct.errorCode, errorStruct.errorDetail); TransportErrorOccuredEventArgs eventargs = WSManTransportManagerUtils.ConstructTransportErrorEventArgs( sessionTM.WSManAPIData.WSManAPIHandle, sessionTM, errorStruct, TransportMethodEnum.SendShellInputEx, RemotingErrorIdStrings.SendExCallBackError, new object[] { sessionTM.ConnectionInfo.ComputerName, WSManTransportManagerUtils.ParseEscapeWSManErrorMessage(errorStruct.errorDetail) }); sessionTM.ProcessWSManTransportError(eventargs); return; } } // Send the next item, if available sessionTM.SendOneItem(); }
// WSMan will make sure this callback is synchronously called ie., if 1 callback // is active, the callback will not be called from a different thread. private static void OnRemoteSessionDataReceived(IntPtr operationContext, int flags, IntPtr error, IntPtr shellOperationHandle, IntPtr commandOperationHandle, IntPtr operationHandle, IntPtr data) { tracer.WriteLine("Client Session TM: OnRemoteDataReceived callback."); long sessionTMHandle = 0; WSManClientSessionTransportManager sessionTM = null; if (!TryGetSessionTransportManager(operationContext, out sessionTM, out sessionTMHandle)) { // We dont have the session TM handle..just return. tracer.WriteLine("Unable to find a transport manager for context {0}.", sessionTMHandle); return; } sessionTM.ClearReceiveOrSendResources(flags, false); if (sessionTM.isClosed) { tracer.WriteLine("Client Session TM: Transport manager is closed. So returning"); return; } if (!shellOperationHandle.Equals(sessionTM._wsManShellOperationHandle)) { // WSMan returned data from a wrong shell..notify the caller // about the same. PSRemotingTransportException e = new PSRemotingTransportException( PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.ReceiveExFailed, sessionTM.ConnectionInfo.ComputerName)); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.ReceiveShellOutputEx); sessionTM.ProcessWSManTransportError(eventargs); return; } if (IntPtr.Zero != error) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) { tracer.WriteLine("Got error with error code {0}. Message {1}", errorStruct.errorCode, errorStruct.errorDetail); TransportErrorOccuredEventArgs eventargs = WSManTransportManagerUtils.ConstructTransportErrorEventArgs( sessionTM.WSManAPIData.WSManAPIHandle, sessionTM, errorStruct, TransportMethodEnum.ReceiveShellOutputEx, RemotingErrorIdStrings.ReceiveExCallBackError, new object[] { sessionTM.ConnectionInfo.ComputerName, WSManTransportManagerUtils.ParseEscapeWSManErrorMessage(errorStruct.errorDetail) }); sessionTM.ProcessWSManTransportError(eventargs); return; } } WSManNativeApi.WSManReceiveDataResult dataReceived = WSManNativeApi.WSManReceiveDataResult.UnMarshal(data); if (null != dataReceived.data) { tracer.WriteLine("Session Received Data : {0}", dataReceived.data.Length); PSEtwLog.LogAnalyticInformational( PSEventId.WSManReceiveShellOutputExCallbackReceived, PSOpcode.Receive, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, sessionTM.RunspacePoolInstanceId.ToString(), Guid.Empty.ToString(), dataReceived.data.Length.ToString(CultureInfo.InvariantCulture)); sessionTM.ProcessRawData(dataReceived.data, dataReceived.stream); } }
/// <summary> /// Launch a new Process (PowerShell.exe -s) to perform remoting. This is used by *-Job cmdlets /// to support background jobs without depending on WinRM (WinRM has complex requirements like /// elevation to support local machine remoting) /// </summary> /// <exception cref="System.InvalidOperationException"> /// </exception> /// <exception cref="System.ComponentModel.Win32Exception"> /// 1. There was an error in opening the associated file. /// </exception> internal override void CreateAsync() { if (null != _connectionInfo) { _processInstance = _connectionInfo.Process ?? new PowerShellProcessInstance(_connectionInfo.PSVersion, _connectionInfo.Credential, _connectionInfo.InitializationScript, _connectionInfo.RunAs32); if (_connectionInfo.Process != null) { _processCreated = false; } // _processInstance.Start(); } PSEtwLog.LogAnalyticInformational(PSEventId.WSManCreateShell, PSOpcode.Connect, PSTask.CreateRunspace, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, RunspacePoolInstanceId.ToString()); try { lock (syncObject) { if (isClosed) { return; } // Attach handlers and start the process _serverProcess = _processInstance.Process; if (_processInstance.RunspacePool != null) { _processInstance.RunspacePool.Close(); _processInstance.RunspacePool.Dispose(); } stdInWriter = _processInstance.StdInWriter; //if (stdInWriter == null) { _serverProcess.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived); _serverProcess.ErrorDataReceived += new DataReceivedEventHandler(OnErrorDataReceived); } _serverProcess.Exited += new EventHandler(OnExited); //serverProcess.Start(); _processInstance.Start(); if (stdInWriter != null) { _serverProcess.CancelErrorRead(); _serverProcess.CancelOutputRead(); } // Start asynchronous reading of output/errors _serverProcess.BeginOutputReadLine(); _serverProcess.BeginErrorReadLine(); stdInWriter = new OutOfProcessTextWriter(_serverProcess.StandardInput); _processInstance.StdInWriter = stdInWriter; } } catch (System.ComponentModel.Win32Exception w32e) { PSRemotingTransportException psrte = new PSRemotingTransportException(w32e, RemotingErrorIdStrings.IPCExceptionLaunchingProcess, w32e.Message); psrte.ErrorCode = w32e.HResult; TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.CreateShellEx); RaiseErrorHandler(eventargs); return; } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); PSRemotingTransportException psrte = new PSRemotingTransportException(PSRemotingErrorId.IPCExceptionLaunchingProcess, RemotingErrorIdStrings.IPCExceptionLaunchingProcess, e.Message); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.CreateShellEx); RaiseErrorHandler(eventargs); return; } // Send one fragment SendOneItem(); }
private void ProcessReaderThread(object state) { try { StreamReader reader = state as StreamReader; Dbg.Assert(reader != null, "Reader cannot be null."); // Send one fragment. SendOneItem(); // Start reader loop. while (true) { string data = reader.ReadLine(); if (data == null) { // End of stream indicates the target process was lost. // Raise transport exception to invalidate the client remote runspace. PSRemotingTransportException psrte = new PSRemotingTransportException( PSRemotingErrorId.IPCServerProcessReportedError, RemotingErrorIdStrings.IPCServerProcessReportedError, RemotingErrorIdStrings.NamedPipeTransportProcessEnded); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.ReceiveShellOutputEx)); break; } if (data.StartsWith(System.Management.Automation.Remoting.Server.NamedPipeErrorTextWriter.ErrorPrepend, StringComparison.OrdinalIgnoreCase)) { // Error message from the server. string errorData = data.Substring(System.Management.Automation.Remoting.Server.NamedPipeErrorTextWriter.ErrorPrepend.Length); HandleErrorDataReceived(errorData); } else { // Normal output data. HandleOutputDataReceived(data); } } } catch (ObjectDisposedException) { // Normal reader thread end. } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); if (e is ArgumentOutOfRangeException) { Dbg.Assert(false, "Need to adjust transport fragmentor to accomodate read buffer size."); } string errorMsg = (e.Message != null) ? e.Message : string.Empty; _tracer.WriteMessage("NamedPipeClientSessionTransportManager", "StartReaderThread", Guid.Empty, "Transport manager reader thread ended with error: {0}", errorMsg); } }
protected void OnExited(object sender, EventArgs e) { TransportMethodEnum transportMethod = TransportMethodEnum.Unknown; lock (syncObject) { // There is no need to return when IsClosed==true here as in a legitimate case process exits // after Close is called..In that legitimate case, Exit handler is removed before // calling Exit..So, this Exit must have been called abnormally. if (isClosed) { transportMethod = TransportMethodEnum.CloseShellOperationEx; } // dont let the writer write new data as the process is exited. // Not assigning null to stdInWriter to fix the race condition between OnExited() and CloseAsync() methods. // stdInWriter.StopWriting(); } PSRemotingTransportException psrte = new PSRemotingTransportException(PSRemotingErrorId.IPCServerProcessExited, RemotingErrorIdStrings.IPCServerProcessExited); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, transportMethod)); }
internal void OnCloseTimeOutTimerElapsed(object source) { PSRemotingTransportException psrte = new PSRemotingTransportException(PSRemotingErrorId.IPCCloseTimedOut, RemotingErrorIdStrings.IPCCloseTimedOut); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.CloseShellOperationEx)); }
protected void HandleErrorDataReceived(string data) { lock (syncObject) { if (isClosed) { return; } } PSRemotingTransportException psrte = new PSRemotingTransportException(PSRemotingErrorId.IPCServerProcessReportedError, RemotingErrorIdStrings.IPCServerProcessReportedError, data); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.Unknown)); }
protected void HandleOutputDataReceived(string data) { try { OutOfProcessUtils.ProcessData(data, _dataProcessingCallbacks); } catch (Exception exception) { CommandProcessorBase.CheckForSevereException(exception); PSRemotingTransportException psrte = new PSRemotingTransportException(PSRemotingErrorId.IPCErrorProcessingServerData, RemotingErrorIdStrings.IPCErrorProcessingServerData, exception.Message); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.ReceiveShellOutputEx)); } }
internal void OnSignalTimeOutTimerElapsed(object source) { //Signal timer is triggered only once if (isClosed) { return; } PSRemotingTransportException psrte = new PSRemotingTransportException(RemotingErrorIdStrings.IPCSignalTimedOut); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.ReceiveShellOutputEx)); }
private static void OnReconnectCmdCompleted(IntPtr operationContext, int flags, IntPtr error, IntPtr shellOperationHandle, IntPtr commandOperationHandle, IntPtr operationHandle, IntPtr data) { long cmdContextId = 0; WSManClientCommandTransportManager cmdTM = null; if (!TryGetCmdTransportManager(operationContext, out cmdTM, out cmdContextId)) { // We dont have the command TM handle..just return. tracer.WriteLine("Unable to find a transport manager for the given command context {0}.", cmdContextId); return; } if ((!shellOperationHandle.Equals(cmdTM._wsManShellOperationHandle)) || (!commandOperationHandle.Equals(cmdTM._wsManCmdOperationHandle))) { // WSMan returned data from a wrong shell..notify the caller // about the same. tracer.WriteLine("Cmd Signal callback: ShellOperationHandles are not the same as the signal is initiated with"); PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.ReconnectShellCommandExCallBackError); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.ReconnectShellCommandEx); cmdTM.ProcessWSManTransportError(eventargs); return; } if (IntPtr.Zero != error) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) { tracer.WriteLine("OnReconnectCmdCompleted callback: WSMan reported an error: {0}", errorStruct.errorDetail); TransportErrorOccuredEventArgs eventargs = WSManTransportManagerUtils.ConstructTransportErrorEventArgs( cmdTM._sessnTm.WSManAPIData.WSManAPIHandle, null, errorStruct, TransportMethodEnum.ReconnectShellCommandEx, RemotingErrorIdStrings.ReconnectShellCommandExCallBackError, new object[] { WSManTransportManagerUtils.ParseEscapeWSManErrorMessage(errorStruct.errorDetail) }); cmdTM.ProcessWSManTransportError(eventargs); return; } } // The command may have been disconnected before all input was read or // the returned command data started to be received. cmdTM._shouldStartReceivingData = true; cmdTM.SendOneItem(); cmdTM.RaiseReconnectCompleted(); }
/// <summary> /// Constructs a WSManTransportErrorOccuredEventArgs instance from the supplied data /// </summary> /// <param name="wsmanAPIHandle"> /// WSMan API handle to use to get error messages from WSMan error id(s) /// </param> /// <param name="wsmanSessionTM"> /// Session Transportmanager to use to get error messages (for redirect) /// </param> /// <param name="errorStruct"> /// Error structure supplied by callbacks from WSMan API /// </param> /// <param name="transportMethodReportingError"> /// The transport method call that reported this error. /// </param> /// <param name="resourceString"> /// resource string that holds the message. /// </param> /// <param name="resourceArgs"> /// Arguments to pass to the resource /// </param> /// <returns> /// An instance of WSManTransportErrorOccuredEventArgs /// </returns> internal static TransportErrorOccuredEventArgs ConstructTransportErrorEventArgs(IntPtr wsmanAPIHandle, WSManClientSessionTransportManager wsmanSessionTM, WSManNativeApi.WSManError errorStruct, TransportMethodEnum transportMethodReportingError, string resourceString, params object[] resourceArgs) { PSRemotingTransportException e; //For the first two special error conditions, it is remotely possible that the wsmanSessionTM is null when the failures are returned //as part of command TM operations (could be returned because of RC retries under the hood) //Not worth to handle these cases separately as there are very corner scenarios, but need to make sure wsmanSessionTM is not referenced // Destination server is reporting that URI redirect is required for this user. if ((errorStruct.errorCode == WSManNativeApi.ERROR_WSMAN_REDIRECT_REQUESTED) && (wsmanSessionTM != null)) { IntPtr wsmanSessionHandle = wsmanSessionTM.SessionHandle; // populate the transport message with the redirection uri..this will // allow caller to make a new connection. string redirectLocation = WSManNativeApi.WSManGetSessionOptionAsString(wsmanSessionHandle, WSManNativeApi.WSManSessionOption.WSMAN_OPTION_REDIRECT_LOCATION); string winrmMessage = ParseEscapeWSManErrorMessage( WSManNativeApi.WSManGetErrorMessage(wsmanAPIHandle, errorStruct.errorCode)).Trim(); e = new PSRemotingTransportRedirectException(redirectLocation, PSRemotingErrorId.URIEndPointNotResolved, RemotingErrorIdStrings.URIEndPointNotResolved, winrmMessage, redirectLocation); } else if ((errorStruct.errorCode == WSManNativeApi.ERROR_WSMAN_INVALID_RESOURCE_URI) && (wsmanSessionTM != null)) { string configurationName = wsmanSessionTM.ConnectionInfo.ShellUri.Replace(Remoting.Client.WSManNativeApi.ResourceURIPrefix, string.Empty); string errorMessage = PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.InvalidConfigurationName, configurationName, wsmanSessionTM.ConnectionInfo.ComputerName); e = new PSRemotingTransportException(PSRemotingErrorId.InvalidConfigurationName, RemotingErrorIdStrings.ConnectExCallBackError, wsmanSessionTM.ConnectionInfo.ComputerName, errorMessage); e.TransportMessage = ParseEscapeWSManErrorMessage( WSManNativeApi.WSManGetErrorMessage(wsmanAPIHandle, errorStruct.errorCode)); } else { // Construct specific error message and then append this message pointing to our own // help topic. PowerShell's about help topic "about_Remote_Troubleshooting" should // contain all the trouble shooting information. string wsManErrorMessage = PSRemotingErrorInvariants.FormatResourceString(resourceString, resourceArgs); e = new PSRemotingTransportException(PSRemotingErrorId.TroubleShootingHelpTopic, RemotingErrorIdStrings.TroubleShootingHelpTopic, wsManErrorMessage); e.TransportMessage = ParseEscapeWSManErrorMessage( WSManNativeApi.WSManGetErrorMessage(wsmanAPIHandle, errorStruct.errorCode)); } e.ErrorCode = errorStruct.errorCode; TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, transportMethodReportingError); return eventargs; }
private static void OnRemoteCmdSignalCompleted(IntPtr operationContext, int flags, IntPtr error, IntPtr shellOperationHandle, IntPtr commandOperationHandle, IntPtr operationHandle, IntPtr data) { tracer.WriteLine("Signal Completed callback received."); long cmdContextId = 0; WSManClientCommandTransportManager cmdTM = null; if (!TryGetCmdTransportManager(operationContext, out cmdTM, out cmdContextId)) { // We dont have the command TM handle..just return. tracer.WriteLine("Unable to find a transport manager for the given command context {0}.", cmdContextId); return; } // log the callback received event. PSEtwLog.LogAnalyticInformational(PSEventId.WSManSignalCallbackReceived, PSOpcode.Disconnect, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, cmdTM.RunspacePoolInstanceId.ToString(), cmdTM.powershellInstanceId.ToString()); if ((!shellOperationHandle.Equals(cmdTM._wsManShellOperationHandle)) || (!commandOperationHandle.Equals(cmdTM._wsManCmdOperationHandle))) { // WSMan returned data from a wrong shell..notify the caller // about the same. tracer.WriteLine("Cmd Signal callback: ShellOperationHandles are not the same as the signal is initiated with"); PSRemotingTransportException e = new PSRemotingTransportException(RemotingErrorIdStrings.CommandSendExFailed); TransportErrorOccuredEventArgs eventargs = new TransportErrorOccuredEventArgs(e, TransportMethodEnum.CommandInputEx); cmdTM.ProcessWSManTransportError(eventargs); return; } // release the resources related to signal if (IntPtr.Zero != cmdTM._cmdSignalOperationHandle) { WSManNativeApi.WSManCloseOperation(cmdTM._cmdSignalOperationHandle, 0); cmdTM._cmdSignalOperationHandle = IntPtr.Zero; } if (null != cmdTM._signalCmdCompleted) { cmdTM._signalCmdCompleted.Dispose(); cmdTM._signalCmdCompleted = null; } // if the transport manager is already closed..ignore the errors and return if (cmdTM.isClosed) { tracer.WriteLine("Client Command TM: Transport manager is closed. So returning"); return; } if (IntPtr.Zero != error) { WSManNativeApi.WSManError errorStruct = WSManNativeApi.WSManError.UnMarshal(error); if (errorStruct.errorCode != 0) { tracer.WriteLine("Cmd Signal callback: WSMan reported an error: {0}", errorStruct.errorDetail); TransportErrorOccuredEventArgs eventargs = WSManTransportManagerUtils.ConstructTransportErrorEventArgs( cmdTM._sessnTm.WSManAPIData.WSManAPIHandle, null, errorStruct, TransportMethodEnum.CommandInputEx, RemotingErrorIdStrings.CommandSendExCallBackError, new object[] { WSManTransportManagerUtils.ParseEscapeWSManErrorMessage(errorStruct.errorDetail) }); cmdTM.ProcessWSManTransportError(eventargs); return; } } cmdTM.EnqueueAndStartProcessingThread(null, null, true); }
private void ProcessErrorThread(object state) { try { StreamReader reader = state as StreamReader; Dbg.Assert(reader != null, "Reader cannot be null."); while (true) { string error = reader.ReadLine(); if (!string.IsNullOrEmpty(error) && (error.IndexOf("WARNING:", StringComparison.OrdinalIgnoreCase) < 0)) { // Any SSH client error results in a broken session. PSRemotingTransportException psrte = new PSRemotingTransportException( PSRemotingErrorId.IPCServerProcessReportedError, RemotingErrorIdStrings.IPCServerProcessReportedError, error); RaiseErrorHandler(new TransportErrorOccuredEventArgs(psrte, TransportMethodEnum.CloseShellOperationEx)); CloseConnection(); } } } catch (ObjectDisposedException) { } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); string errorMsg = (e.Message != null) ? e.Message : string.Empty; _tracer.WriteMessage("SSHClientSessionTransportManager", "ProcessErrorThread", Guid.Empty, "Transport manager error thread ended with error: {0}", errorMsg); } }