Reputation: 11
I'm wondering what would be the optimal way to search against a large list (50k+) hostnames against 5 domains using Get-ADComputer.
The idea i have is that you have an array of $domains and a list of hostnames.
Foreach ($domain in $domains) {
$results = $hostnames | ForEach-Object { Get-ADComputer -Server $domain -Filter "Name -eq '$($_)'" -Properties * } | Out-DataTable
There is no SearchBase because we're not sure where in the AD structure the machine can be and obviously we don't know which domain it is. The properties is a * since i'm looking for everything back. Even if it were limited, we'd be looking at least 8-10 properties minimum. I did toy with the idea of removing items from the $hostnames list as something is found.
Upvotes: 0
Views: 1165
Reputation: 41008
The network requests are going to hurt you the most. The key to speed is getting the number of network requests down.
I wrote an article about getting better performance while working with AD. One thing I talked about was asking for as much as you can at a time. The idea is to use multiple "or" conditions to get multiple objects back in one query. The example I wrote there is in C#, but you can adapt it for PowerShell, which I made an attempt at below. It will do one search for a group of 50 computer names. You might get away with 100 or more. The limit for one LDAP query (not just the query string, but the whole query package) is 10MB.
Removing the names as you find them is also a good idea, which I took the liberty to add. You have to convert the array to a List
to be able to use .Remove()
.
$hostnames = [Collections.Generic.List[String]]$hostnames
Foreach ($domain in $domains) {
$filter = ""
$count = 0
For ($i=0; $i -lt $hostnames.Count; $i++) {
if ($filter -eq "") {
$filter += "Name -eq $($hostnames[$i])"
} else {
$filter += " -or Name -eq $($hostnames[$i])"
}
$count++
#check if we have 50 names in the filter, or we're on our last one
if ($count -eq 50 -or $i -eq $hostnames.Count - 1) {
$found = Get-ADComputer -Server $domain -Filter $filter -Properties *
$found | Out-DataTable
$found | ForEach {
$hostnames.Remove($_.Name) > $null
}
$filter = ""
}
}
}
If all 5 domains are in the same AD forest, then you can get rid of the domain loop and search the Global Catalog. Then you wouldn't need to bother removing found names from the list either. You do that by passing the the GC port to the -Server
parameter:
$found = Get-ADComputer -Server "$($domain):3268" -Filter $filter -Properties *
Upvotes: 1