New-PSSession wants a -ConnectionURI of an explict Exchange server. I don't want to hardcode a name in the script (we have 32 servers), and furthermore I want it to select an exchange that is in the same datacenter.
I want a solution similar to Get-ADDomainController -Discover -GetClosestSite But it seems I'm hoping for too much.
I suppose I can pull the members of cn=Exchange Install Domain Servers and do some site dependent ranking on them.
Looking for best practices.
Update Edit: 9/26 I have achieved a solution. It may be site specific, but I'll share below in an answer to show the final code. The answer provided by postanote provided pointers that helped me move forward.
There is no official documented best practices for PowerShell in general (there are too many variables in the mix, but some have put their thoughts in the topic , for example, this one - https://github.com/PoshCode/PowerShellPracticeAndStyle ) or for what you are asking for from Microsoft.
As for you point here:
I suppose I can pull the members of cn=Exchange Install Domain Servers and do some site dependent ranking on them.
This is not something new, or tricky, so you can do this.
I have code in my personal library that I use that does this as well as for other doing resources, so I never have to hardcode server names for Exchange, SQL, DC, etc.
There are several blogs (that have been out there for a while now) on the topic with sample code to use as is or tweak as needed, which is why I asked what you've searched for.
One of those blog examples of how to do this is here:
https://use-powershell.blogspot.com/2012/12/find-exchange-servers-in-domain.html
The examples provided:
- an active directory user with mailbox will have 2 attributes (msExchHomeServerName and homemdb) that will contain the name of the mailbox server that has his mailbox - once conected to one server you can use exchange console to find the rest of them;
Get-ADUser samaccountname -Properties msExchHomeServerName, homemdb |Select-Object msExchHomeServerName, homemdb |Format-List
- active directory computer type objects contain "exchange" word in servicePrincipalName attribute; you can use only your organizational unit that contain your servers if you have one to narrow your search:
Get-ADComputer -Filter * -SearchBase 'OU= SERVERS, DC=domain_name,DC=net' -Properties * | Where-Object {$_.serviceprincipalname -like '*exchange*'} |select-object name
- active directory configuration partition contain information about exchange servers in domain; you can search for objects of class msExchExchangeServer:
Get-ADObject -LDAPFilter "(objectClass=msExchExchangeServer)" –SearchBase "CN=Configuration,DC=domainname,DC=net" | Select-Object name
or you can list all objects from "CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=INTERNAL,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domainname,DC=net" using powershell or ADSI Edit console;
Get-ADObject -Filter * -SearchBase "CN=Servers,CN=First Administrative Group,CN=Administrative Groups,CN=INTERNAL,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domainname,DC=net" -SearchScope onelevel
Or this post:
Example:
dsquery * "cn=Configuration,dc=MyDomain,dc=com" -Filter "(objectCategory=msExchExchangeServer)"
Or if you are really trying to get an Exchange server in given site, then this to already exists. See this GitHub source:
https://github.com/mikepfeiffer/PowerShell/blob/master/Get-ExchangeServerInSite.ps1
The sample provided is:
function Get-ExchangeServerInSite {
$ADSite = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]
$siteDN = $ADSite::GetComputerSite().GetDirectoryEntry().distinguishedName
$configNC=([ADSI]"LDAP://RootDse").configurationNamingContext
$search = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$configNC")
$objectClass = "objectClass=msExchExchangeServer"
$version = "versionNumber>=1937801568"
$site = "msExchServerSite=$siteDN"
$search.Filter = "(&($objectClass)($version)($site))"
$search.PageSize=1000
[void] $search.PropertiesToLoad.Add("name")
[void] $search.PropertiesToLoad.Add("msexchcurrentserverroles")
[void] $search.PropertiesToLoad.Add("networkaddress")
$search.FindAll() | %{
New-Object PSObject -Property @{
Name = $_.Properties.name[0]
FQDN = $_.Properties.networkaddress |
%{if ($_ -match "ncacn_ip_tcp") {$_.split(":")[1]}}
Roles = $_.Properties.msexchcurrentserverroles[0]
}
}
}