/// <summary>
        /// Handle session closing event to close runspace pool drivers this session is hosting.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        private void HandleSessionDSHandlerClosing(object sender, EventArgs eventArgs)
        {
            if (null != _runspacePoolDriver)
            {
                _runspacePoolDriver.Close();
            }

            // dispose the session configuration object..this will let them
            // clean their resources.
            if (null != _sessionConfigProvider)
            {
                _sessionConfigProvider.Dispose();
                _sessionConfigProvider = null;
            }
        }
Beispiel #2
0
 private void HandleSessionDSHandlerClosing(object sender, EventArgs eventArgs)
 {
     if (this._runspacePoolDriver != null)
     {
         this._runspacePoolDriver.Close();
     }
     if (this._sessionConfigProvider != null)
     {
         this._sessionConfigProvider.Dispose();
         this._sessionConfigProvider = null;
     }
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="createRunspaceEventArg"></param>
        /// <exception cref="InvalidOperationException">
        /// 1. InitialSessionState cannot be null.
        /// 2. Non existent InitialSessionState provider for the shellID
        /// </exception>
        private void HandleCreateRunspacePool(object sender, RemoteDataEventArgs createRunspaceEventArg)
        {
            if (createRunspaceEventArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("createRunspaceEventArg");
            }
            RemoteDataObject<PSObject> rcvdData = createRunspaceEventArg.ReceivedData;
            Dbg.Assert(rcvdData != null, "rcvdData must be non-null");

            // set the PSSenderInfo sent in the first packets
            // This is used by the initial session state configuration providers like Exchange.
            if (Context != null)
            {
#if !CORECLR // TimeZone Not In CoreCLR
                _senderInfo.ClientTimeZone = Context.ClientCapability.TimeZone;
#endif
            }

            _senderInfo.ApplicationArguments = RemotingDecoder.GetApplicationArguments(rcvdData.Data);

            // Get Initial Session State from custom session config suppliers
            // like Exchange.
            ConfigurationDataFromXML configurationData =
                PSSessionConfiguration.LoadEndPointConfiguration(_configProviderId,
                    _initParameters);
            // used by Out-Of-Proc (IPC) runspace.
            configurationData.InitializationScriptForOutOfProcessRunspace = _initScriptForOutOfProcRS;
            // start with data from configuration XML and then override with data
            // from EndPointConfiguration type.
            _maxRecvdObjectSize = configurationData.MaxReceivedObjectSizeMB;
            _maxRecvdDataSizeCommand = configurationData.MaxReceivedCommandSizeMB;

            DISCPowerShellConfiguration discProvider = null;

            if (String.IsNullOrEmpty(configurationData.ConfigFilePath))
            {
                _sessionConfigProvider = configurationData.CreateEndPointConfigurationInstance();
            }
            else
            {
                System.Security.Principal.WindowsPrincipal windowsPrincipal = new System.Security.Principal.WindowsPrincipal(_senderInfo.UserInfo.WindowsIdentity);

                Func<string, bool> validator = (role) => windowsPrincipal.IsInRole(role);

                discProvider = new DISCPowerShellConfiguration(configurationData.ConfigFilePath, validator);
                _sessionConfigProvider = discProvider;
            }

            // exchange of ApplicationArguments and ApplicationPrivateData is be done as early as possible
            // (i.e. to let the _sessionConfigProvider bail out if it can't comply with client's versioning request)
            PSPrimitiveDictionary applicationPrivateData = _sessionConfigProvider.GetApplicationPrivateData(_senderInfo);

            InitialSessionState rsSessionStateToUse = null;

            if (configurationData.SessionConfigurationData != null)
            {
                try
                {
                    rsSessionStateToUse =
                        _sessionConfigProvider.GetInitialSessionState(configurationData.SessionConfigurationData, _senderInfo, _configProviderId);
                }
                catch (NotImplementedException)
                {
                    rsSessionStateToUse = _sessionConfigProvider.GetInitialSessionState(_senderInfo);
                }
            }
            else
            {
                rsSessionStateToUse = _sessionConfigProvider.GetInitialSessionState(_senderInfo);
            }

            if (null == rsSessionStateToUse)
            {
                throw PSTraceSource.NewInvalidOperationException(RemotingErrorIdStrings.InitialSessionStateNull, _configProviderId);
            }

            rsSessionStateToUse.ThrowOnRunspaceOpenError = true;

            // this might throw if the sender info is already present
            rsSessionStateToUse.Variables.Add(
                new SessionStateVariableEntry(RemoteDataNameStrings.SenderInfoPreferenceVariable,
                _senderInfo,
                Remoting.PSRemotingErrorInvariants.FormatResourceString(
                    RemotingErrorIdStrings.PSSenderInfoDescription),
                ScopedItemOptions.ReadOnly));

            // check if the current scenario is Win7(client) to Win8(server). Add back the PSv2 version TabExpansion
            // function if necessary.
            Version psClientVersion = null;
            if (_senderInfo.ApplicationArguments != null && _senderInfo.ApplicationArguments.ContainsKey("PSversionTable"))
            {
                var value = PSObject.Base(_senderInfo.ApplicationArguments["PSversionTable"]) as PSPrimitiveDictionary;
                if (value != null)
                {
                    if (value.ContainsKey("WSManStackVersion"))
                    {
                        var wsmanStackVersion = PSObject.Base(value["WSManStackVersion"]) as Version;
                        if (wsmanStackVersion != null && wsmanStackVersion.Major < 3)
                        {
                            // The client side is PSv2. This is the Win7 to Win8 scenario. We need to add the PSv2 
                            // TabExpansion function back in to keep the tab expansion functionable on the client side.
                            rsSessionStateToUse.Commands.Add(
                                new SessionStateFunctionEntry(
                                    RemoteDataNameStrings.PSv2TabExpansionFunction,
                                    RemoteDataNameStrings.PSv2TabExpansionFunctionText));
                        }
                    }
                    if (value.ContainsKey("PSVersion"))
                    {
                        psClientVersion = PSObject.Base(value["PSVersion"]) as Version;
                    }
                }
            }

            if (!string.IsNullOrEmpty(configurationData.EndPointConfigurationTypeName))
            {
                // user specified a type to load for configuration..use the values from this type.
                _maxRecvdObjectSize = _sessionConfigProvider.GetMaximumReceivedObjectSize(_senderInfo);
                _maxRecvdDataSizeCommand = _sessionConfigProvider.GetMaximumReceivedDataSizePerCommand(_senderInfo);
            }
            SessionDataStructureHandler.TransportManager.ReceivedDataCollection.MaximumReceivedObjectSize = _maxRecvdObjectSize;
            // MaximumReceivedDataSize is not set for session transport manager...see the constructor
            // for more info.

            Guid clientRunspacePoolId = rcvdData.RunspacePoolId;
            int minRunspaces = RemotingDecoder.GetMinRunspaces(rcvdData.Data);
            int maxRunspaces = RemotingDecoder.GetMaxRunspaces(rcvdData.Data);
            PSThreadOptions threadOptions = RemotingDecoder.GetThreadOptions(rcvdData.Data);
#if !CORECLR // No ApartmentState In CoreCLR
            ApartmentState apartmentState = RemotingDecoder.GetApartmentState(rcvdData.Data);
#endif
            HostInfo hostInfo = RemotingDecoder.GetHostInfo(rcvdData.Data);

            if (_runspacePoolDriver != null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.RunspaceAlreadyExists,
                    _runspacePoolDriver.InstanceId);
            }

#if !UNIX
            bool isAdministrator = _senderInfo.UserInfo.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
#else
            bool isAdministrator = false;
#endif

            ServerRunspacePoolDriver tmpDriver = new ServerRunspacePoolDriver(
                clientRunspacePoolId,
                minRunspaces,
                maxRunspaces,
                threadOptions,
#if !CORECLR // No ApartmentState In CoreCLR
                apartmentState,
#endif
                hostInfo,
                rsSessionStateToUse,
                applicationPrivateData,
                configurationData,
                this.SessionDataStructureHandler.TransportManager,
                isAdministrator,
                Context.ServerCapability,
                psClientVersion,
                _configurationName);

            // attach the necessary event handlers and start the driver.
            Interlocked.Exchange(ref _runspacePoolDriver, tmpDriver);
            _runspacePoolDriver.Closed += HandleResourceClosing;
            _runspacePoolDriver.Start();
        }
Beispiel #4
0
        private void HandleCreateRunspacePool(object sender, RemoteDataEventArgs createRunspaceEventArg)
        {
            if (createRunspaceEventArg == null)
            {
                throw PSTraceSource.NewArgumentNullException("createRunspaceEventArg");
            }
            RemoteDataObject<PSObject> receivedData = createRunspaceEventArg.ReceivedData;
            if (this._context != null)
            {
				if (this._context.ClientCapability == null) {
					this._senderInfo.ClientTimeZone = this._context.ServerCapability.TimeZone;
				}
				else {
					this._senderInfo.ClientTimeZone = this._context.ClientCapability.TimeZone;
				}
            }
            this._senderInfo.ApplicationArguments = RemotingDecoder.GetApplicationArguments(receivedData.Data);
            ConfigurationDataFromXML configData = PSSessionConfiguration.LoadEndPointConfiguration(this._configProviderId, this._initParameters);
            configData.InitializationScriptForOutOfProcessRunspace = this._initScriptForOutOfProcRS;
            this.maxRecvdObjectSize = configData.MaxReceivedObjectSizeMB;
            this.maxRecvdDataSizeCommand = configData.MaxReceivedCommandSizeMB;
            DISCPowerShellConfiguration configuration = null;
            if (string.IsNullOrEmpty(configData.ConfigFilePath))
            {
                this._sessionConfigProvider = configData.CreateEndPointConfigurationInstance();
            }
            else
            {
                configuration = new DISCPowerShellConfiguration(configData.ConfigFilePath);
                this._sessionConfigProvider = configuration;
            }
            PSPrimitiveDictionary applicationPrivateData = this._sessionConfigProvider.GetApplicationPrivateData(this._senderInfo);
            InitialSessionState initialSessionState = null;
            if (configData.SessionConfigurationData != null)
            {
                try
                {
                    initialSessionState = this._sessionConfigProvider.GetInitialSessionState(configData.SessionConfigurationData, this._senderInfo, this._configProviderId);
                }
                catch (NotImplementedException)
                {
                    initialSessionState = this._sessionConfigProvider.GetInitialSessionState(this._senderInfo);
                }
            }
            else
            {
                initialSessionState = this._sessionConfigProvider.GetInitialSessionState(this._senderInfo);
            }
            if (initialSessionState == null)
            {
                throw PSTraceSource.NewInvalidOperationException("RemotingErrorIdStrings", "InitialSessionStateNull", new object[] { this._configProviderId });
            }
            initialSessionState.ThrowOnRunspaceOpenError = true;
            initialSessionState.Variables.Add(new SessionStateVariableEntry("PSSenderInfo", this._senderInfo, PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.PSSenderInfoDescription, new object[0]), ScopedItemOptions.ReadOnly));
            if ((this._senderInfo.ApplicationArguments != null) && this._senderInfo.ApplicationArguments.ContainsKey("PSversionTable"))
            {
                PSPrimitiveDictionary dictionary2 = PSObject.Base(this._senderInfo.ApplicationArguments["PSversionTable"]) as PSPrimitiveDictionary;
                if ((dictionary2 != null) && dictionary2.ContainsKey("WSManStackVersion"))
                {
                    Version version = PSObject.Base(dictionary2["WSManStackVersion"]) as Version;
                    if ((version != null) && (version.Major < 3))
                    {
                        initialSessionState.Commands.Add(new SessionStateFunctionEntry("TabExpansion", "\r\n            param($line, $lastWord)\r\n            & {\r\n                function Write-Members ($sep='.')\r\n                {\r\n                    Invoke-Expression ('$_val=' + $_expression)\r\n\r\n                    $_method = [Management.Automation.PSMemberTypes] `\r\n                        'Method,CodeMethod,ScriptMethod,ParameterizedProperty'\r\n                    if ($sep -eq '.')\r\n                    {\r\n                        $params = @{view = 'extended','adapted','base'}\r\n                    }\r\n                    else\r\n                    {\r\n                        $params = @{static=$true}\r\n                    }\r\n        \r\n                    foreach ($_m in ,$_val | Get-Member @params $_pat |\r\n                        Sort-Object membertype,name)\r\n                    {\r\n                        if ($_m.MemberType -band $_method)\r\n                        {\r\n                            # Return a method...\r\n                            $_base + $_expression + $sep + $_m.name + '('\r\n                        }\r\n                        else {\r\n                            # Return a property...\r\n                            $_base + $_expression + $sep + $_m.name\r\n                        }\r\n                    }\r\n                }\r\n\r\n                # If a command name contains any of these chars, it needs to be quoted\r\n                $_charsRequiringQuotes = ('`&@''#{}()$,;|<> ' + \"`t\").ToCharArray()\r\n\r\n                # If a variable name contains any of these characters it needs to be in braces\r\n                $_varsRequiringQuotes = ('-`&@''#{}()$,;|<> .\\/' + \"`t\").ToCharArray()\r\n\r\n                switch -regex ($lastWord)\r\n                {\r\n                    # Handle property and method expansion rooted at variables...\r\n                    # e.g. $a.b.<tab>\r\n                    '(^.*)(\\$(\\w|:|\\.)+)\\.([*\\w]*)$' {\r\n                        $_base = $matches[1]\r\n                        $_expression = $matches[2]\r\n                        $_pat = $matches[4] + '*'\r\n                        Write-Members\r\n                        break;\r\n                    }\r\n\r\n                    # Handle simple property and method expansion on static members...\r\n                    # e.g. [datetime]::n<tab>\r\n                    '(^.*)(\\[(\\w|\\.|\\+)+\\])(\\:\\:|\\.){0,1}([*\\w]*)$' {\r\n                        $_base = $matches[1]\r\n                        $_expression = $matches[2]\r\n                        $_pat = $matches[5] + '*'\r\n                        Write-Members $(if (! $matches[4]) {'::'} else {$matches[4]})\r\n                        break;\r\n                    }\r\n\r\n                    # Handle complex property and method expansion on static members\r\n                    # where there are intermediate properties...\r\n                    # e.g. [datetime]::now.d<tab>\r\n                    '(^.*)(\\[(\\w|\\.|\\+)+\\](\\:\\:|\\.)(\\w+\\.)+)([*\\w]*)$' {\r\n                        $_base = $matches[1]  # everything before the expression\r\n                        $_expression = $matches[2].TrimEnd('.') # expression less trailing '.'\r\n                        $_pat = $matches[6] + '*'  # the member to look for...\r\n                        Write-Members\r\n                        break;\r\n                    }\r\n\r\n                    # Handle variable name expansion...\r\n                    '(^.*\\$)([*\\w:]+)$' {\r\n                        $_prefix = $matches[1]\r\n                        $_varName = $matches[2]\r\n                        $_colonPos = $_varname.IndexOf(':')\r\n                        if ($_colonPos -eq -1)\r\n                        {\r\n                            $_varName = 'variable:' + $_varName\r\n                            $_provider = ''\r\n                        }\r\n                        else\r\n                        {\r\n                            $_provider = $_varname.Substring(0, $_colonPos+1)\r\n                        }\r\n\r\n                        foreach ($_v in Get-ChildItem ($_varName + '*') | sort Name)\r\n                        { \r\n                            $_nameFound = $_v.name\r\n                            $(if ($_nameFound.IndexOfAny($_varsRequiringQuotes) -eq -1) {'{0}{1}{2}'}\r\n                            else {'{0}{{{1}{2}}}'}) -f $_prefix, $_provider, $_nameFound\r\n                        }\r\n                        break;\r\n                    }\r\n\r\n                    # Do completion on parameters...\r\n                    '^-([*\\w0-9]*)' {\r\n                        $_pat = $matches[1] + '*'\r\n\r\n                        # extract the command name from the string\r\n                        # first split the string into statements and pipeline elements\r\n                        # This doesn't handle strings however.\r\n                        $_command = [regex]::Split($line, '[|;=]')[-1]\r\n\r\n                        #  Extract the trailing unclosed block e.g. ls | foreach { cp\r\n                        if ($_command -match '\\{([^\\{\\}]*)$')\r\n                        {\r\n                            $_command = $matches[1]\r\n                        }\r\n\r\n                        # Extract the longest unclosed parenthetical expression...\r\n                        if ($_command -match '\\(([^()]*)$')\r\n                        {\r\n                            $_command = $matches[1]\r\n                        }\r\n\r\n                        # take the first space separated token of the remaining string\r\n                        # as the command to look up. Trim any leading or trailing spaces\r\n                        # so you don't get leading empty elements.\r\n                        $_command = $_command.TrimEnd('-')\r\n                        $_command,$_arguments = $_command.Trim().Split()\r\n\r\n                        # now get the info object for it, -ArgumentList will force aliases to be resolved\r\n                        # it also retrieves dynamic parameters\r\n                        try\r\n                        {\r\n                            $_command = @(Get-Command -type 'Alias,Cmdlet,Function,Filter,ExternalScript' `\r\n                                -Name $_command -ArgumentList $_arguments)[0]\r\n                        }\r\n                        catch\r\n                        {\r\n                            # see if the command is an alias. If so, resolve it to the real command\r\n                            if(Test-Path alias:\\$_command)\r\n                            {\r\n                                $_command = @(Get-Command -Type Alias $_command)[0].Definition\r\n                            }\r\n\r\n                            # If we were unsuccessful retrieving the command, try again without the parameters\r\n                            $_command = @(Get-Command -type 'Cmdlet,Function,Filter,ExternalScript' `\r\n                                -Name $_command)[0]\r\n                        }\r\n\r\n                        # remove errors generated by the command not being found, and break\r\n                        if(-not $_command) { $error.RemoveAt(0); break; }\r\n\r\n                        # expand the parameter sets and emit the matching elements\r\n                        # need to use psbase.Keys in case 'keys' is one of the parameters\r\n                        # to the cmdlet\r\n                        foreach ($_n in $_command.Parameters.psbase.Keys)\r\n                        {\r\n                            if ($_n -like $_pat) { '-' + $_n }\r\n                        }\r\n                        break;\r\n                    }\r\n\r\n                    # Tab complete against history either #<pattern> or #<id>\r\n                    '^#(\\w*)' {\r\n                        $_pattern = $matches[1]\r\n                        if ($_pattern -match '^[0-9]+$')\r\n                        {\r\n                            Get-History -ea SilentlyContinue -Id $_pattern | Foreach { $_.CommandLine } \r\n                        }\r\n                        else\r\n                        {\r\n                            $_pattern = '*' + $_pattern + '*'\r\n                            Get-History -Count 32767 | Sort-Object -Descending Id| Foreach { $_.CommandLine } | where { $_ -like $_pattern }\r\n                        }\r\n                        break;\r\n                    }\r\n\r\n                    # try to find a matching command...\r\n                    default {\r\n                        # parse the script...\r\n                        $_tokens = [System.Management.Automation.PSParser]::Tokenize($line,\r\n                            [ref] $null)\r\n\r\n                        if ($_tokens)\r\n                        {\r\n                            $_lastToken = $_tokens[$_tokens.count - 1]\r\n                            if ($_lastToken.Type -eq 'Command')\r\n                            {\r\n                                $_cmd = $_lastToken.Content\r\n\r\n                                # don't look for paths...\r\n                                if ($_cmd.IndexOfAny('/\\:') -eq -1)\r\n                                {\r\n                                    # handle parsing errors - the last token string should be the last\r\n                                    # string in the line...\r\n                                    if ($lastword.Length -ge $_cmd.Length -and \r\n                                        $lastword.substring($lastword.length-$_cmd.length) -eq $_cmd)\r\n                                    {\r\n                                        $_pat = $_cmd + '*'\r\n                                        $_base = $lastword.substring(0, $lastword.length-$_cmd.length)\r\n\r\n                                        # get files in current directory first, then look for commands...\r\n                                        $( try {Resolve-Path -ea SilentlyContinue -Relative $_pat } catch {} ;\r\n                                           try { $ExecutionContext.InvokeCommand.GetCommandName($_pat, $true, $false) |\r\n                                               Sort-Object -Unique } catch {} ) |\r\n                                                   # If the command contains non-word characters (space, ) ] ; ) etc.)\r\n                                                   # then it needs to be quoted and prefixed with &\r\n                                                   ForEach-Object {\r\n                                                        if ($_.IndexOfAny($_charsRequiringQuotes) -eq -1) { $_ }\r\n                                                        elseif ($_.IndexOf('''') -ge 0) {'& ''{0}''' -f $_.Replace('''','''''') }\r\n                                                        else { '& ''{0}''' -f $_ }} |\r\n                                                   ForEach-Object {'{0}{1}' -f $_base,$_ }\r\n                                    }\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        "));
                    }
                }
            }
            if (!string.IsNullOrEmpty(configData.EndPointConfigurationTypeName))
            {
                this.maxRecvdObjectSize = this._sessionConfigProvider.GetMaximumReceivedObjectSize(this._senderInfo);
                this.maxRecvdDataSizeCommand = this._sessionConfigProvider.GetMaximumReceivedDataSizePerCommand(this._senderInfo);
            }
            this._sessionDSHandler.TransportManager.ReceivedDataCollection.MaximumReceivedObjectSize = this.maxRecvdObjectSize;
            Guid runspacePoolId = receivedData.RunspacePoolId;
            int minRunspaces = RemotingDecoder.GetMinRunspaces(receivedData.Data);
            int maxRunspaces = RemotingDecoder.GetMaxRunspaces(receivedData.Data);
            PSThreadOptions threadOptions = RemotingDecoder.GetThreadOptions(receivedData.Data);
            ApartmentState apartmentState = RemotingDecoder.GetApartmentState(receivedData.Data);
            HostInfo hostInfo = RemotingDecoder.GetHostInfo(receivedData.Data);
            if (this._runspacePoolDriver != null)
            {
                throw new PSRemotingDataStructureException(RemotingErrorIdStrings.RunspaceAlreadyExists, new object[] { this._runspacePoolDriver.InstanceId });
            }
            bool isAdministrator = this._senderInfo.UserInfo.IsInRole(WindowsBuiltInRole.Administrator);
            ServerRunspacePoolDriver driver = new ServerRunspacePoolDriver(runspacePoolId, minRunspaces, maxRunspaces, threadOptions, apartmentState, hostInfo, initialSessionState, applicationPrivateData, configData, this.SessionDataStructureHandler.TransportManager, isAdministrator, this._context.ServerCapability, (configuration == null) ? null : configuration.ConfigHash);
            Interlocked.Exchange<ServerRunspacePoolDriver>(ref this._runspacePoolDriver, driver);
            this._runspacePoolDriver.Closed = (EventHandler<EventArgs>) Delegate.Combine(this._runspacePoolDriver.Closed, new EventHandler<EventArgs>(this.HandleResourceClosing));
            this._runspacePoolDriver.Start();
        }