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
}