protected void Start(string initialCommand, PSRemotingCryptoHelperServer cryptoHelper, string configurationName = null) { _initialCommand = initialCommand; sessionTM = CreateSessionTransportManager(configurationName, cryptoHelper); try { do { string data = originalStdIn.ReadLine(); lock (_syncObject) { if (sessionTM == null) { sessionTM = CreateSessionTransportManager(configurationName, cryptoHelper); } } if (string.IsNullOrEmpty(data)) { lock (_syncObject) { // give a chance to runspace/pipelines to close (as it looks like the client died // interminently) sessionTM.Close(null); sessionTM = null; } throw new PSRemotingTransportException(PSRemotingErrorId.IPCUnknownElementReceived, RemotingErrorIdStrings.IPCUnknownElementReceived, string.Empty); } // process data in a thread pool thread..this way Runspace, Command // data can be processed concurrently. #if CORECLR ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessingThreadStart), data); #else Utils.QueueWorkItemWithImpersonation( _windowsIdentityToImpersonate, new WaitCallback(ProcessingThreadStart), data); #endif } while (true); } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); PSEtwLog.LogOperationalError( PSEventId.TransportError, PSOpcode.Open, PSTask.None, PSKeyword.UseAlwaysOperational, Guid.Empty.ToString(), Guid.Empty.ToString(), OutOfProcessUtils.EXITCODE_UNHANDLED_EXCEPTION, e.Message, e.StackTrace); PSEtwLog.LogAnalyticError( PSEventId.TransportError_Analytic, PSOpcode.Open, PSTask.None, PSKeyword.Transport | PSKeyword.UseAlwaysAnalytic, Guid.Empty.ToString(), Guid.Empty.ToString(), OutOfProcessUtils.EXITCODE_UNHANDLED_EXCEPTION, e.Message, e.StackTrace); if (_exitProcessOnError) { // notify the remote client of any errors and fail gracefully originalStdErr.WriteLine(e.Message); Environment.Exit(OutOfProcessUtils.EXITCODE_UNHANDLED_EXCEPTION); } } }
/// <summary> /// Log an error message. /// </summary> private static void LogError(PSEventId eventId, params object[] args) { PSEtwLog.LogOperationalError(eventId, PSOpcode.Constructor, PSTask.ExperimentalFeature, PSKeyword.UseAlwaysOperational, args); }
private void ProcessListeningThread(object state) { string processId = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture); string appDomainName = NamedPipeUtils.GetCurrentAppDomainName(); // Logging. _tracer.WriteMessage("RemoteSessionNamedPipeServer", "StartListening", Guid.Empty, "Listener thread started on Process {0} in AppDomainName {1}.", processId, appDomainName); PSEtwLog.LogOperationalInformation( PSEventId.NamedPipeIPC_ServerListenerStarted, PSOpcode.Open, PSTask.NamedPipe, PSKeyword.UseAlwaysOperational, processId, appDomainName); Exception ex = null; string userName = string.Empty; bool restartListenerThread = true; // Wait for connection. try { // Begin listening for a client connect. this.WaitForConnection(); try { userName = WindowsIdentity.GetCurrent().Name; } catch (System.Security.SecurityException) { } // Logging. _tracer.WriteMessage("RemoteSessionNamedPipeServer", "StartListening", Guid.Empty, "Client connection started on Process {0} in AppDomainName {1} for User {2}.", processId, appDomainName, userName); PSEtwLog.LogOperationalInformation( PSEventId.NamedPipeIPC_ServerConnect, PSOpcode.Connect, PSTask.NamedPipe, PSKeyword.UseAlwaysOperational, processId, appDomainName, userName); // Create reader/writer streams. TextReader = new StreamReader(Stream); TextWriter = new StreamWriter(Stream); TextWriter.AutoFlush = true; } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); ex = e; } if (ex != null) { // Error during connection handling. Don't try to restart listening thread. string errorMessage = !string.IsNullOrEmpty(ex.Message) ? ex.Message : string.Empty; _tracer.WriteMessage("RemoteSessionNamedPipeServer", "StartListening", Guid.Empty, "Unexpected error in listener thread on process {0} in AppDomainName {1}. Error Message: {2}", processId, appDomainName, errorMessage); PSEtwLog.LogOperationalError(PSEventId.NamedPipeIPC_ServerListenerError, PSOpcode.Exception, PSTask.NamedPipe, PSKeyword.UseAlwaysOperational, processId, appDomainName, errorMessage); Dispose(); return; } // Start server session on new connection. ex = null; try { Action <RemoteSessionNamedPipeServer> clientConnectCallback = state as Action <RemoteSessionNamedPipeServer>; Dbg.Assert(clientConnectCallback != null, "Client callback should never be null."); // Handle a new client connect by making the callback. // The callback must handle all exceptions except // for a named pipe disposed or disconnected exception // which propagates up to the thread listener loop. clientConnectCallback(this); } catch (IOException) { // Expected connection terminated. } catch (ObjectDisposedException) { // Expected from PS transport close/dispose. } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); ex = e; restartListenerThread = false; } // Logging. _tracer.WriteMessage("RemoteSessionNamedPipeServer", "StartListening", Guid.Empty, "Client connection ended on process {0} in AppDomainName {1} for User {2}.", processId, appDomainName, userName); PSEtwLog.LogOperationalInformation( PSEventId.NamedPipeIPC_ServerDisconnect, PSOpcode.Close, PSTask.NamedPipe, PSKeyword.UseAlwaysOperational, processId, appDomainName, userName); if (ex == null) { // Normal listener exit. _tracer.WriteMessage("RemoteSessionNamedPipeServer", "StartListening", Guid.Empty, "Listener thread ended on process {0} in AppDomainName {1}.", processId, appDomainName); PSEtwLog.LogOperationalInformation(PSEventId.NamedPipeIPC_ServerListenerEnded, PSOpcode.Close, PSTask.NamedPipe, PSKeyword.UseAlwaysOperational, processId, appDomainName); } else { // Unexpected error. string errorMessage = !string.IsNullOrEmpty(ex.Message) ? ex.Message : string.Empty; _tracer.WriteMessage("RemoteSessionNamedPipeServer", "StartListening", Guid.Empty, "Unexpected error in listener thread on process {0} in AppDomainName {1}. Error Message: {2}", processId, appDomainName, errorMessage); PSEtwLog.LogOperationalError(PSEventId.NamedPipeIPC_ServerListenerError, PSOpcode.Exception, PSTask.NamedPipe, PSKeyword.UseAlwaysOperational, processId, appDomainName, errorMessage); } lock (_syncObject) { IsListenerRunning = false; } // Ensure this named pipe server object is disposed. Dispose(); ListenerEnded.SafeInvoke( this, new ListenerEndedEventArgs(ex, restartListenerThread)); }