iterating active directory
In my script to detect Service Pack 2, I queried Active Directory for a list of computers and then looped through them.
This script pattern -- looping through a set of users and computers -- is something that I'm going to use quite often with PowerShell, so I decided to make two functions out of it. The first returns a list of computers and the second returns a list users. From there, I can simply use a foreach loop and save a lot of repetitive work.
update: I've updated the script to account for online computers only using WMI and win32_pingstatus.
function iter-computers (
[string]$ldapString=$(throw 'LDAP String is required'),
[switch]$pingable
) {
$entry = new-object system.directoryservices.directoryentry($ldapString)
$search = new-object system.directoryservices.directorysearcher($entry)
$search.filter = '(objectCategory=Computer)'
if ($pingable) {
$onlineComputers = @()
$computers = $search.findAll()
foreach ($computer in $computers) {
$query = "select * from win32_pingstatus where address = '{0}'" `
-f [string]$computer.properties.name
$queryResult = get-wmiobject -query $query
if ($queryResult.protocoladdress) {
$onlineComputers += $computer
}
}
$onlineComputers
} else {
@($search.findAll())
}
}
function iter-users ($ldapString=$(throw 'LDAP String is required')) {
$entry = new-object system.directoryservices.directoryentry($ldapString)
$search = new-object system.directoryservices.directorysearcher($entry)
$search.filter = '(objectCategory=User)'
@($search.findall())
}
Each function requires a standard LDAP string such as LDAP://ou=sales,dc=domain,dc=com. The results are casted to an array to make them iterable.
Here's a quick example:
foreach ($computer in iter-computers "LDAP://ou=sales,dc=domain,dc=com") {
$computer.properties.name
}
Here's an example using the new pingable option:
foreach ($online in iter-computers $ldapString -pingable) {
$online.properties.name
}
