尝试在 Powershell 中动态连接到最近的 Exchange 服务器

Trying to dynamically connect in Powershell to nearest Exchange Server

New-PSSession 需要显式 Exchange 服务器的 -ConnectionURI。我不想在脚本中硬编码名称(我们有 32 台服务器),而且我希望它成为 select 位于同一数据中心的交换。

我想要一个类似于 Get-ADDomainController -Discover -GetClosestSite 的解决方案但是我似乎希望太多了。

我想我可以提取 cn=Exchange Install Domain Servers 的成员并对它们进行一些站点相关的排名。

寻找最佳实践。

更新编辑:9/26 我已经找到了解决方案。它可能是特定于站点的,但我将在下面的答案中分享以显示最终代码。 postanote 提供的答案提供了帮助我前进的指针。

PowerShell 总体上没有官方记录的最佳实践(混合变量太多,但有些人已经将他们的想法放在主题中,例如,这个 - https://github.com/PoshCode/PowerShellPracticeAndStyle)或您向 Microsoft 提出的要求。

至于你点这里:

I suppose I can pull the members of cn=Exchange Install Domain Servers and do some site dependent ranking on them.

这不是什么新鲜事,也不是什么棘手的事,所以你可以做到。

我的个人图书馆中有我使用的代码,可以执行此操作以及其他资源,因此我永远不必为 Exchange、SQL、DC 等硬编码服务器名称

有几个博客(已经存在一段时间了)关于这个主题的示例代码可以按原样使用或根据需要进行调整,这就是为什么我问你搜索了什么。

此处是有关如何执行此操作的博客示例之一:

https://use-powershell.blogspot.com/2012/12/find-exchange-servers-in-domain.html

提供的示例:

  1. 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
  1. 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
  1. 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 

或者这个post:

https://social.technet.microsoft.com/Forums/ie/en-US/94d89161-9dfb-48fc-b307-2f0e1320c9dc/how-to-find-file-servers-and-exchange-servers-in-ad-

示例:

dsquery * "cn=Configuration,dc=MyDomain,dc=com" -Filter "(objectCategory=msExchExchangeServer)"

或者,如果您真的想在给定站点中获取 Exchange 服务器,那么这已经存在。请参阅此 GitHub 来源:

https://github.com/mikepfeiffer/PowerShell/blob/master/Get-ExchangeServerInSite.ps1

提供的样本是:

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]
        }
    }
}

我接受 postanote 的回答是最有帮助的。

最后,我创建了一个可能特定于站点和 Exchange 安装的解决方案,但它确实说明了另一种技术。

我的约束不同于我发现并包含的大多数其他解决方案;给定用户当前在系统上没有邮箱。因此,此代码段之外的代码将收集一些数据,然后 select 一个特定的数据库。

我发现我们安装的 Exchange 服务器版本在 "CN=Exchange Install Domain Servers,CN=Microsoft Exchange System Objects," 中创建了一些记录,特别是 Members 属性有一个服务器列表。 我提取了该列表,按站点(从本地到前面)对其进行排序,然后解析 FQDN 以形成要连接的 URI。

Function Connect-Exchange {
     #  Find servers list, then sort by name given what site we are running in:  SITE1 = Ascending , SITE2 = Descending
     $ADSite = (Get-ADDomainController).Site
     if ($ADSite -like "SITE1*") { $descOrder =  $true } else { $descOrder = $false }
     $exchSession = $null                                     
     $ExchServersDN = "CN=Exchange Install Domain Servers,CN=Microsoft Exchange System Objects,DC=example,DC=com”
     $ExchServers = (Get-ADObject -Identity $($ExchServersDN) -Properties Member).Member | Sort-Object -Descending:$descOrder 

     # Iterate through Exchange server list until connection succeeds
     $i = 0;
     while ((-Not $exchSession) -and ($i -lt $ExchServers.Count)) { 
        $ExchServerURI = "http://" + (Get-ADObject -Identity $ExchServers[$i] -Properties dNSHostName).dnsHostName + "/Powershell"
        $exchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionURI $ExchServerURI  -ErrorAction SilentlyContinue
        If (-Not $exchSession)  { $i++ }
        else {                                                                 
            Import-PSSession $exchSession -DisableNameChecking | Out-Null
        }
     }
     return $exchSession
}