Quick Learn – Implicit Remoting and the Exchange Cmdlets

I work in an environment where we administer Microsoft Exchange 2010 and I’m proud to say that I don’t have the Exchange Management Tools installed on my laptop. Now, that doesn’t mean I don’t sometimes RDP into an Exchange box, but it does force me to forgo that and use Windows PowerShell when I want to do something quicker than to RDP, log on, and open the EMC. One of the first things I added to my $PROFILE, after writing it for use in a script, was a function that would establish a PSSession to one of the Exchange servers. This allows me to run Exchange-specific cmdlets without leaving my laptop and without having the Exchange Management Tools installed.

The first thing I started with was an empty function that I called New-ExchangeSession.

Function New-ExchangeSession {

}

I had a few requirements for this project. One, I didn’t want to rely on connecting to the same Exchange server each time I created a PSSession. If for some reason it wasn’t available, I would have a problem connecting… in addition to a non-responsive Exchange server. Two, I didn’t want to hard code my Exchange server list in either my script (bad!) or in an external file (not as bad, but not great). What I did was make use of the Get-ADGroupMember and the Get-Random cmdlets to return the names of the Exchange Servers from an Active Directory group in which they were all members, and then randomly select one.

I did this as part of Do-Until loop. In line 3, the first thing it does is acquire the members of the group, ExchangeServers, using the Get-ADGroupMember cmdlet included in the Active Directory module. If you’re running PowerShell 3.0 or greater it will load this module automatically. If you’re not, then you’ll have to add it yourself using the Import-Module cmdlet before beginning the Do-Until loop.

Using dotted notation (.Name) we return only the Name property of the group members. Once collected, the Get-Random cmdlet is used to randomly select one of the names and then assign it to the $ExchServ variable.

Function New-ExchangeSession {
    Do {
        $ExchServ = Get-Random (Get-ADGroupMember -Identity 'ExchangeServers').Name
    }
    Until (Test-Connection -ComputerName $ExchServ -Count 1 -Quiet)
}

If you’re using something older than 3.0, and you really shouldn’t be, you’ll find the dotted notation version just doesn’t work as expected. In that case, you will have to handle this in a more procedural way as seen in the example below. Regardless of which way you get a server name and assign it to the $ExchServ variable, it must reply to a ping, by use of the Test-Connection cmdlet in line 5 above, and line 7 below. This is the conditional check of Do-Until loop. If Test-Connection returns True, it will break out of the Do-Until. If it returns False, it will randomly select another server and try again.

Function New-ExchangeSession {
    Do {
        $ExchServ = Get-ADGroupMember -Identity 'ExchangeServers'
        $ExchServ = Get-Random $ExchServ
        $ExchServ = $ExchServ.Name
    }
    Until (Test-Connection -ComputerName $ExchServ -Count 1 -Quiet)
}

We start to create the PSSession once we have an Exchange server name chosen and verified it is reachable across the network. This is done by creating a variable, $Session on line 7 below, that will store the session information. We then use that session information as part of our Import-PSSession cmdlet that brings the Exchange cmdlets down to our local computer. The final, informational message on line 9 simply indicates the Exchange server in which we’ve connected.

Function New-ExchangeSession {
    Do {
        $ExchServ = Get-Random (Get-ADGroupMember -Identity 'ExchangeServers').Name
    }
    Until (Test-Connection -ComputerName $ExchServ -Count 1 -Quiet)

    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://$ExchServ.mydomain.com/powershell" -Authentication Kerberos
    Import-PSSession -Session $Session -CommandName * -FormatTypeName * | Out-Null
    Write-Output "Connected to $ExchServ"
}

You will often, if not always, receive a warning about some of the imported commands may have unapproved verbs. To view your active session, use the Get-PSSession cmdlet, and to close the session, use the Remove-PSSession -Id  #, where # equals the Id number returned from the Get-PSSession cmdlet.