Simplify creating a remote PowerShell connection (part 1)

For this example, I’ll be establishing a connection to Exchange 2010. My problem is that I’m lazy and that’s why I always script things out. the function is no different. Everytime I do this it’s the same process and if you’re like me, I usually have 4+ PowerShell windows open at a time. Using this function helps to make things easy for me.

When I do something multiple times I take out parts that change and they become variables in my script. Let’s look at a simple one-line command for creating a remote connection to (in this case) Exchange.

$Session = New-PSSession -ConfigurationName "Microsoft.Exchange" `
-ConnectionUri "http://$server/PowerShell/" -Authentication kerberos

if you want to logon with different credentials you can runas PowerShell, or you can have New-PSSession prompt you using -Credential $(get-credential) in place of -Authentication kerberos like this:

$Session = New-PSSession `
-ConfigurationName "Microsoft.Exchange" -ConnectionUri "http://$server/PowerShell/" -Credential $(get-credential)

With this second version of the command you get the GUI popup asking for your credentials and all subsequent Exchange commands will use these credentials.

So, in these two commands, the only thing that has changed is the $server variable and if you use remote powershell to Exchange, it doesn’t really matter which server you connect to. You may have a preference, based on server resources, but really it doesn’t matter. Although if you’re in New York I wouldn’t connect to the server in Australia!

Makin’ it easy!
So, to make my life easier, I do a dot-import of my ExchangeFunctions.ps1 file which has two things. the first thing it has is an array of preferred Exchange server names.

$arrExchangeServers = @("mbx1","mbx2","cas1","cas2","hub1","hub2")

The second thing I have is a function called Get-Exchange2010PSSession. In this function, I have PowerShell do all the work and pick a random server for me. There is also a small optimisation that I’ll talk about later. Let’s get to the function…

function Get-Exchange2010PSSession
{
<#
.SYNOPSIS
    Returns a PSSession from a randomly chosen Exchange server 
    based on the list of servers supplied
.DESCRIPTION
    Returns a PSSession from a randomly chosen Exchange server 
    based on the list of servers supplied
.EXAMPLE
    Get-Exchange2010PSSession -ServerList @("server1","server2")
.PARAMETER ServerList
    String array of Exchange 2010 FQDN server names.
#>
    [CmdletBinding(SupportsShouldProcess=$true)]
    param(
        [Parameter(Mandatory=$true)]
        # ServerList is an array of FQDN server names
        [string[]]    $ServerList
    )
    begin{
        $ErrorActionPreference = "Stop"
        $session = $null
    }
    Process{
        do
        {
            $server = get-random -inputObject $serverList
            try
            {
                $psSessionOption = new-pssessionoption `
                      -culture $(get-UICulture) `
                      -NoMachineProfile `
                      -OpenTimeOut 30000 `
                      -SkipCACheck
                $Session = New-PSSession `
                      -ConfigurationName "Microsoft.Exchange" `
                      -ConnectionUri "http://$server/PowerShell/" `
                      -Authentication kerberos `
                      -SessionOption $psSessionOption
            }
            catch
            {
                $msg = "There was an exception trying to get a "
                $msg += "session from http://$server/PowerShell/"
                Write-host -fore red $msg
                Write-host -fore red "$error[0]"
            }
        } until ($session -ne $null)
        return $session
    }
    end {
    }
}

Walk through
Walking through this function we start with the basic documentation. The first parameter $ServerList is a string array. This is the list we defined earlier in the exchangeFunctions.ps1 file. In the Begin { } section the $ErrorActionPreference is set to “Stop” This way our try { } catch{ } will work and we set what will become our resulting $session variable to a default of $null.

Within the process{ } section we start a do{ } until (condition) statement that will loop through the server list choosing a random server in the list. Remember, we will be getting the same set of commands from each server so it doesn’t really matter which server we connect to. Personally, I like to have the system choose a random server because I don’t want to get into the habbit of always running my code on the same system. Next is a try{ } catch { } block that does two things.

  1. Set the PowerShell Session Options with New-PSSessionOption. I’ll go over this later so we’ll skip this until the end.
  2. Create the new PS Session with New-PSSession using whatever the currently selected server.

If there is an error the function will echo it out in the catch { }. The function will continually try a different server untill $Session is successfully populated with a return from New-PSSession. Once that happens, Get-Exchange2010PSSession returns that $Session variable which you can import using Import-PSSession.

New-PSSessionOption
What about that New-PSSessionOption bit? Well, did you know the default time out for establising a session is 3 minutes? If you’re like me, you don’t want to wait that long. As a result, I setup my own PSSessionOption and set the time out to 30 seconds (30,000 miliseconds). I also set the culture. I don’t need to download the russian or chinese version of the commands, I don’t speak those languages. Using Get-UICulture I get the culture settings on the systems. The other two options probably don’t speed things up very much, but I like to think I’m sucking the marrow out of PowerShell with them. If you’re curious, check them out with

Help New-PSSessionOption -detailed

Next Time…
Next time I’ll show you how to make this even easier with an additional PowerShell functions that does ALL the work in setting up a remote PowerShell session

Leave a Reply