EHLO blog: Remote PowerShell Proxying Behavior in Exchange 2013 CU12 and Exchange 2016

In Exchange 2013 CU11, we introduced a change to the way Remote PowerShell (RPS) functioned.

Prior to CU11, Exchange 2013 routed Remote PowerShell requests by finding a random mailbox that is either higher than the ExchClientVer that is specified in the URL, or if the ExchClientVer is not specified, by using the current CAS version in which the client connected. We refer to this behavior as server version-based routing.

With CU11, we changed Remote PowerShell to route requests to an anchor mailbox. Typically, this anchor mailbox would be the mailbox of the user attempting the connection. In the event the user attempting the connection did not have a mailbox, the request would be routed to the organization arbitration mailbox.

There were several perceived benefits with this approach:

  1. This approach solved an issue with coexistence and ensured that RPS is executed based on the version of the mailbox executing the action. The server version-based routing behavior prior to CU11 led to scenarios where a client could receive the following error:Complete error:

    New-PSSession : [] Processing data from remote server failed with the
    following error message: [ClientAccessServer=E2K13-1,,RequestId=76229690-2343-4
    f-9a51-48184587c5cf,TimeStamp=8/14/2015 2:20:36 PM] [FailureCategory=WSMan-InvalidShellID] The request for the Window
    Remote Shell with ShellId DD266254-5C1F-43C0-A4DA-1797C253C0C0 failed because the shell was not found on the server.
    Possible causes are: the specified ShellId is incorrect or the shell no longer exists on the server. Provide the
    correct ShellId or create a new shell and retry the operation. For more information, see the
    about_Remote_Troubleshooting Help topic.
    At C:\Scripts\test.ps1:8 char:12
    + $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri ht …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (System.Manageme….RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemoti
    + FullyQualifiedErrorId : CannotConnectTargetSessionDoesNotExist,PSSessionOpenFailed
    Import-PSSession : Cannot validate argument on parameter ‘Session’. The argument is null. Provide a valid value for
    the argument, and then try running the command again.
    At C:\Scripts\test.ps1:10 char:18
    + Import-PSSession $Session
    + ~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Import-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ImportPSSessionCommand

    This error occurs when a load balanced RPS request shifts from one version of Exchange to another, whether that be Exchange 2013 coexisting with Exchange 2016, or different versions of cumulative updates for the same version of Exchange.

  2. This approach utilized the same code path for Remote PowerShell proxying in Office 365.

Unfortunately, the changes in CU11 introduced several issues with Remote PowerShell in the on-premises world that we did not anticipate. After reviewing each issue and performing an in-depth code review, we made the decision to revert the CU11 change and return to utilizing server version-based routing for Remote PowerShell requests beginning in Exchange 2013 CU12. Exchange 2016 (including CU1) will also use server version-based routing.

If you were planning to take advantage of the changes in Remote PowerShell routing in CU11, you may now be wondering what options are available to you beginning in CU12. Fortunately, you have several options:

  1. When connecting to Exchange via Remote PowerShell, specify a server FQDN instead of a load balanced namespace.

    $cred = Get-Credential
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Authentication Kerberos -Credential $cred
    Import-PSSession $Session

    For more information, please see the TechNet article, Connect to Exchange servers using Remote PowerShell.

  2. When connecting to Exchange via Remote PowerShell and specifying a load balanced namespace, specify the ExchClientVer value for the server version you wish to connect against.

    $cred = Get-Credential
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri “;ExchClientVer=″ -Authentication Basic -Credential $cred
    Import-PSSession $Session

  3. Configure the load balancer to use session affinity for Remote PowerShell requests.
  4. Remove the older Exchange versions from the load balanced pool.

We will continue to evaluate ways we can improve the routing of Remote PowerShell requests for on-premises deployments.

Leave a Reply

Your email address will not be published. Required fields are marked *