Задача: имеется список guid-ов объектов в AD, для которых необходимо получить некоторый набор свойств. Объекты могут быть как пользователями, так и группами или контактами. Искать нужно внутри многодоменного леса, объекты могут быть внутри любого домена в лесе. Найти объект, вне зависимости от его типа, можно через командлет Get-ADObject:
Get-ADObject $guid
Небольшое затруднение возникает, если необходимо делать поиск по всем доменам одного леса. Очевидное решение в лоб – взять список доменов и в каждом из них провести поиск:
$Domains = (Get-ADForest).Domains ForEach ($Domain in $Domains) { $Search = Get-ADObject $guid -Server (Get-ADDomain $Domain).PDCEmulator -ErrorAction Stop }
Работать будет, но с ошибками. Очевидно, что по-конкретному guid-у объект будет возвращаться только из одного домена. Поиск в остальных доменах вернёт ошибку, так как такого объекта там не будет. Поэтому имеет смысл внести в скрипт try-catch:
$Domains = (Get-ADForest).Domains $Results = @() ForEach ($Domain in $Domains) { try { $Search = Get-ADObject $guid -Server (Get-ADDomain $Domain).PDCEmulator -ErrorAction Stop $Found = $true } catch { $Found = $false } If ($Found) { $Results += New-Object PSObject -Property @{ guid = $guid Domain = $Domain DistinguishedName = $Search.DistinguishedName ObjectClass = $Search.ObjectClass Found = $Found } } }
Добавляем загрузку из txt-файла списка guid-ов:
$guids = Import-Csv -Path C:\guids.txt $Domains = (Get-ADForest).Domains $Results = @() ForEach ($guid in $guids) { ForEach ($Domain in $Domains) { try { $Search = Get-ADObject $guid -Server (Get-ADDomain $Domain).PDCEmulator -ErrorAction Stop $Found = $true } catch { $Found = $false } If ($Found) { $Results += New-Object PSObject -Property @{ guid = $guid Domain = $Domain DistinguishedName = $Search.DistinguishedName ObjectClass = $Search.ObjectClass Found = $Found } } } } $Results | Where { $_.Found } | Select guid,Domain,DistinguishedName,ObjectClass,Found
Задача решена и можно запускать скрипт и ждать. Если доменов у нас с десяток, объектов для поиска больше сотни, то ждать придётся долго. Что с эти делать? Искать в глобальном каталоге! Правда, стоит помнить, что он содержит не все аттрибуты объектов. Для поиска в глобальном каталоге используем тот же Get-ADObject, но в ключе -Server нужно будет указать любой ближайший глобальный каталог, по-умолчанию доступный при обращении к порту 3268:
$LocalSite = (Get-ADDomainController -Discover).Site $NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -SiteName $LocalSite if (!$NewTargetGC) { $NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -NextClosestSite } $NewTargetGCHostName = $NewTargetGC.HostName $LocalGC = "$NewTargetGCHostName" + ":3268"
Try-catch при таком поиске нам будет нужен разве что для обработки поиска несуществующих guid-ов. Скрипт немного упростится:
$guids = Import-Csv -Path C:\guids.txt $Results = @() $LocalSite = (Get-ADDomainController -Discover).Site $NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -SiteName $LocalSite if (!$NewTargetGC) { $NewTargetGC = Get-ADDomainController -Discover -Service GlobalCatalog -NextClosestSite } $NewTargetGCHostName = $NewTargetGC.HostName $LocalGC = "$NewTargetGCHostName" + ":3268" ForEach ($guid in $guids) { Try { $Search = Get-ADObject -Identity $guid.guid -Server $LocalGC } Catch { } $Results += New-Object PSObject -Property @{ guid = $guid.guid DistinguishedName = $Search.DistinguishedName ObjectClass = $Search.ObjectClass } } $Results | Select guid,DistinguishedName,ObjectClass
Скрипт при этом отрабатывать будет на пару порядков быстрее.
Полезные ссылки:
Powershell Code: Discover a Local Global Catalog for Forest Queries
PowerShell Code: Find User in Active Directory Forest
Get-ADDomainController
Get-ADObject