« PowerShell Community Extensions (PSCX) | Main | PowerShell – less code, same result »
Searching Active Directory for Windows 2000 and Windows NT4 Domain Controllers with PowerShell
By Adam Bell | February 20, 2007
When I posted the article on raising AD functionality levels recently David Saxon pointed out that more could be done in regards to confirming the Domain Controllers are at the required level, i.e. they are Windows 2003 Domain Controllers.
Since we’ve looked at searching the Directory yesterday, this seems like a good time to take a closer look into this.
Microsoft have a good article here on what features are available depending on you functionality level.
So we’d start with:
$query = new-object system.directoryservices.directorysearcher
$root = [adsi]""
And presuming our DC’s are located in the default location, we can narrow our search down:
$ou = [adsi]("LDAP://ou=Domain Controllers,"+$root.distinguishedName)
$query.SearchRoot = $ou
$query.SearchScope = "OneLevel"
The key to our search is going to be the filter() that we use. If you look around there’s a few different ways of identifying what we might want to search on.
In KB article 322692 there is a good filter for finding NT4 Domain Controllers:
$query.filter = "(&(objectCategory=computer)(operatingSystem Version=4*)(userAccountControl:1.2.840.113556.1.4.803:=8192))"
Here we’re filtering on the computer object, the OS version, and the UAC value. Let’s break this down a bit more. The first one is pretty obvious, the OS version is easy enough too. Anything with a 4 in the version relates to NT4. Windows 2000 is 5.0, and Windows 2003 is 5.2. So what’s with the UAC filter? The bitwise filter is an Object ID (OID) that means all the flags have to be set for a match. The value of 8192 specifies that the account is a Domain Controller.
We can search for Windows 2000 Domain Controllers using the following filter, as described in KB article 325379
$query.filter = "(&(objectCategory=computer)(primaryGroupID=516)(operatingSystemVersion=5.0*))"
Similar to the above example, we’re filtering on the computer object again. This time rather than use the UAC approach though we’ve used the PrimaryGroupID which we’ve touched on previously. The OS version corresponds to the versions discussed above.
It seems to me that our best approach would be to filter on any computer account, that’s not Windows 2003. As we’re only searching in the Domain Controllers OU we shouldn’t need to try and check the UAC or Primary Group information, but you could just to be sure if you felt that way inclined.
$query.filter = "(&(objectCategory=computer)(!operatingSystem Version=5.2*)(userAccountControl:1.2.840.113556.1.4.803:=8192))"
There’s a subtle difference between this filter and the first example. Basically we’re looking for OS version that’s not (!) equal to Windows 2003. In theory this should give us all the other Domain Controllers ;)
So to finish off then:
$result = $query.FindAll()
if ($result -eq $null)
{
return $null
}
else
{
foreach ($machine in $result)
{
$ADobject = $machine.GetDirectoryEntry()
write-host $ADobject.distinguishedName
}
}
Of course just because we have accounts in AD doesn’t actually mean that there are machines still out there. You could tie this into a function that then calls a ping test against the names that are retrieved. That’s still not gospel, but if it’s a DC, it’s more likely to be up if it’s still out there!
If you’re new to LDAP queries and would like more information Microsoft have a good primer here.
- Searching Active Directory with PowerShell
- Managing group membership in Active Directory with PowerShell (Part 1)
- Raising Active Directory Domain and Forest functionality to Windows 2003 with PowerShell
- Managing group membership in Active Directory with PowerShell (Part 2)
- Enabling and disabling a Global Catalog server with PowerShell
Topics: Active Directory, PowerShell | No Comments »