Задача: имеется список 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