/// <summary> /// Constructor for ServerRemoteHost. /// </summary> internal ServerRemoteHost( Guid clientRunspacePoolId, Guid clientPowerShellId, HostInfo hostInfo, AbstractServerTransportManager transportManager, Runspace runspace, ServerDriverRemoteHost serverDriverRemoteHost) { _clientRunspacePoolId = clientRunspacePoolId; _clientPowerShellId = clientPowerShellId; Dbg.Assert(hostInfo != null, "Expected hostInfo != null"); Dbg.Assert(transportManager != null, "Expected transportManager != null"); // Set host-info and the transport-manager. HostInfo = hostInfo; _transportManager = transportManager; _serverDriverRemoteHost = serverDriverRemoteHost; // Create the executor for the host methods. _serverMethodExecutor = new ServerMethodExecutor( clientRunspacePoolId, clientPowerShellId, _transportManager); // Use HostInfo to create host-UI as null or non-null based on the client's host-UI. _remoteHostUserInterface = hostInfo.IsHostUINull ? null : new ServerRemoteHostUserInterface(this); Runspace = runspace; }
/// <summary> /// Creates the runspace pool driver /// </summary> /// <param name="clientRunspacePoolId">client runspace pool id to associate</param> /// <param name="transportManager">transport manager associated with this /// runspace pool driver</param> /// <param name="maxRunspaces">maximum runspaces to open</param> /// <param name="minRunspaces">minimum runspaces to open</param> /// <param name="threadOptions">threading options for the runspaces in the pool</param> /// <param name="apartmentState">apartment state for the runspaces in the pool</param> /// <param name="hostInfo">host information about client side host</param> /// <param name="configData"> /// Contains: /// 1. Script to run after a RunspacePool/Runspace is created in this session. /// For RunspacePool case, every newly created Runspace (in the pool) will run /// this script. /// 2. ThreadOptions for RunspacePool/Runspace /// 3. ThreadApartment for RunspacePool/Runspace /// </param> /// <param name="initialSessionState">configuration of the runspace</param> /// <param name="applicationPrivateData">application private data</param> /// <param name="isAdministrator">True if the driver is being created by an administrator</param> /// <param name="serverCapability">server capability reported to the client during negotiation (not the actual capability)</param> /// <param name="psClientVersion">Client PowerShell version.</param> /// <param name="configurationName">Optional endpoint configuration name to create a pushed configured runspace.</param> internal ServerRunspacePoolDriver( Guid clientRunspacePoolId, int minRunspaces, int maxRunspaces, PSThreadOptions threadOptions, ApartmentState apartmentState, HostInfo hostInfo, InitialSessionState initialSessionState, PSPrimitiveDictionary applicationPrivateData, ConfigurationDataFromXML configData, AbstractServerSessionTransportManager transportManager, bool isAdministrator, RemoteSessionCapability serverCapability, Version psClientVersion, string configurationName) #endif { Dbg.Assert(null != configData, "ConfigurationData cannot be null"); _serverCapability = serverCapability; _clientPSVersion = psClientVersion; _configurationName = configurationName; // Create a new server host and associate for host call // integration _remoteHost = new ServerDriverRemoteHost(clientRunspacePoolId, Guid.Empty, hostInfo, transportManager, null); _configData = configData; _applicationPrivateData = applicationPrivateData; RunspacePool = RunspaceFactory.CreateRunspacePool( minRunspaces, maxRunspaces, initialSessionState, _remoteHost); // Set ThreadOptions for this RunspacePool // The default server settings is to make new commands execute in the calling thread...this saves // thread switching time and thread pool pressure on the service. // Users can override the server settings only if they are administrators PSThreadOptions serverThreadOptions = configData.ShellThreadOptions.HasValue ? configData.ShellThreadOptions.Value : PSThreadOptions.UseCurrentThread; if (threadOptions == PSThreadOptions.Default || threadOptions == serverThreadOptions) { RunspacePool.ThreadOptions = serverThreadOptions; } else { if (!isAdministrator) { throw new InvalidOperationException(PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.MustBeAdminToOverrideThreadOptions)); } RunspacePool.ThreadOptions = threadOptions; } #if !CORECLR // No ApartmentState In CoreCLR // Set Thread ApartmentState for this RunspacePool ApartmentState serverApartmentState = configData.ShellThreadApartmentState.HasValue ? configData.ShellThreadApartmentState.Value : Runspace.DefaultApartmentState; if (apartmentState == ApartmentState.Unknown || apartmentState == serverApartmentState) { RunspacePool.ApartmentState = serverApartmentState; } else { RunspacePool.ApartmentState = apartmentState; } #endif // If we have a runspace pool with a single runspace then we can run nested pipelines on // on it in a single pipeline invoke thread. if (maxRunspaces == 1 && (RunspacePool.ThreadOptions == PSThreadOptions.Default || RunspacePool.ThreadOptions == PSThreadOptions.UseCurrentThread)) { _driverNestedInvoker = new PowerShellDriverInvoker(); } InstanceId = clientRunspacePoolId; DataStructureHandler = new ServerRunspacePoolDataStructureHandler(this, transportManager); // handle the StateChanged event of the runspace pool RunspacePool.StateChanged += new EventHandler<RunspacePoolStateChangedEventArgs>(HandleRunspacePoolStateChanged); // listen for events on the runspace pool RunspacePool.ForwardEvent += new EventHandler<PSEventArgs>(HandleRunspacePoolForwardEvent); RunspacePool.RunspaceCreated += HandleRunspaceCreated; // register for all the events from the data structure handler DataStructureHandler.CreateAndInvokePowerShell += new EventHandler<RemoteDataEventArgs<RemoteDataObject<PSObject>>>(HandleCreateAndInvokePowerShell); DataStructureHandler.GetCommandMetadata += new EventHandler<RemoteDataEventArgs<RemoteDataObject<PSObject>>>(HandleGetCommandMetadata); DataStructureHandler.HostResponseReceived += new EventHandler<RemoteDataEventArgs<RemoteHostResponse>>(HandleHostResponseReceived); DataStructureHandler.SetMaxRunspacesReceived += new EventHandler<RemoteDataEventArgs<PSObject>>(HandleSetMaxRunspacesReceived); DataStructureHandler.SetMinRunspacesReceived += new EventHandler<RemoteDataEventArgs<PSObject>>(HandleSetMinRunspacesReceived); DataStructureHandler.GetAvailableRunspacesReceived += new EventHandler<RemoteDataEventArgs<PSObject>>(HandleGetAvailableRunspacesReceived); DataStructureHandler.ResetRunspaceState += new EventHandler<RemoteDataEventArgs<PSObject>>(HandleResetRunspaceState); }