Share via


Remote PowerShell in Exchange 2013

Over the past couple weeks, I've dealt with a few customers who've wanted to demystify the options available to them when running remote PowerShell scripts against their Exchange environment. This may be for a number of reasons: automated provisioning of user accounts, regular scheduled account clean up, statistics reporting et al.

The way we recommend to connect to PowerShell from a remote computer is a method called implicit remoting. This involves connecting to your local PowerShell session, and importing the remote PowerShell session that's running on your Exchange server. However, there are some caveats to this, which I'll address after the below "how-to" for this method:

  1. On your local computer, open Windows PowerShell and execute the following command:

     $UserCredential = Get-Credential
    
  2. After entering the credentials prompted when you executed the above command, execute the following:

     $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://<FQDN of Exchange 2013 Client Access server>/PowerShell/ -Authentication Kerberos -Credential $UserCredential
    
  3. Finally, import the session established above with the following:

     Import-PSSession $Session
    

Congratulations: all the Exchange cmdlets have been imported into your local session, and will be executed against the remote session established.

HOWEVER, and it's a big one, there are some limitations to implicit remoting in this way. When your local computer sends a script to the remote Exchange server, the code is serialized first -  when it gets to the Exchange server it’s converted back (deserialized) and executed. The result is serialized again and sent back to your local computer. This can cause havoc with carefully crafted scripts that expect the original data to be returned in its original format (with all methods available and intact). If we want to execute methods on the “real” object within the Exchange environment we need to do that on Exchange's end. 

To do this, we need to change the language mode on the PowerShell virtual directory from RestrictedLanguage to FullLanguage. This is because, in RestrictedLanguage mode, commands that contain scripts that need to be evaluated are not allowed. We do this by modifying the web.config file within the PowerShell virtual directory and changing the value to FullLanguage. Now, instead of importing the session, we can simply make use of Invoke-Command against the session to run any commands within your script: Invoke-Command -Session $Session 

Have fun!