Other Posts in this Series:
This post includes an example of how we can use ADSI to list nested members of an AD group. In other words, if the group contains nested groups, it will iteratively search all the members of those nested groups too.
I’ve filtered this first example to only find enabled objects for those organisations that don’t do good housekeeping!
function Find-Enabled-Members
{
Param
(
[string]$DN
)
if (!([adsi]::Exists("LDAP://$DN"))) {
write-host "$DN does not exist"
return
}
$foundCount = 0
$group = [adsi]("LDAP://$DN")
($group).member | ForEach-Object {
$groupObject = [adsisearcher]"(&(distinguishedname=$($_)))"
$groupObjectProps = $groupObject.FindOne().Properties
if ($groupObjectProps.objectcategory -like "CN=group*") {
#search nested group
$foundCount += Find-Enabled-Members "$_"
} else {
$objenabled = ($groupObjectProps.useraccountcontrol[0] -band 2) -ne 2
if ($objenabled) {
write-host "Found $($groupObjectProps.samaccountname) in $($group.Name)"
$foundCount += 1
}
}
}
return $foundCount
}
#group to search for
$groupName = "Alkane_AD_Group"
$objSearcher=[adsisearcher]"(&(objectCategory=group)(name=$groupName))"
$objSearcher.PageSize = 200
#specify properties to include
$colProplist = "name","distinguishedname"
foreach ($i in $colPropList) { $objSearcher.PropertiesToLoad.Add($i) | out-null }
$group = $objSearcher.FindOne()
if ($group -ne $null)
{
#if group found
$name = ($group.Properties).name
$distinguishedName = ($group.Properties).distinguishedname
write-host "Found group $name. Searching members..."
#find members
$members = Find-Enabled-Members $distinguishedName
write-host "Total enabled members including nested members is $members"
}
Since it’s checking if each member is enabled or not, it does take slightly longer to run. If you just wanted to check the member count whether it’s disabled or enabled, you can use the following example:
function Find-Members
{
Param
(
[string]$DN
)
if (!([adsi]::Exists("LDAP://$DN"))) {
write-host "$DN does not exist"
return
}
$group = [adsi]("LDAP://$DN")
$foundCount = $group.Member.Count
($group).member | ForEach-Object {
$groupObject = [adsisearcher]"(&(distinguishedname=$($_)))"
$groupObj = $groupObject.FindOne()
if ($groupObj -ne $null) {
$groupObjectProps = $groupObj.Properties
if ($groupObjectProps.objectcategory -like "CN=group*") {
#get path of the object from search result
$pathToObject = ($groupObjectProps).adspath[0]
#convert/cast search result object path to an ADSI object
$obj = [adsi]($pathToObject)
#subtract one to deduct group object (we only want to count the members)
$foundCount = $foundCount - 1
$foundCount += Find-Members "$_"
}
}
}
return $foundCount
}
#group to search for
$groupName = "Alkane_AD_Group"
$objSearcher=[adsisearcher]"(&(objectCategory=group)(name=$groupName))"
$objSearcher.PageSize = 200
#specify properties to include
$colProplist = "name","distinguishedname"
foreach ($i in $colPropList) { $objSearcher.PropertiesToLoad.Add($i) | out-null }
$group = $objSearcher.FindOne()
if ($group -ne $null)
{
#if group found
$name = ($group.Properties).name
$distinguishedName = ($group.Properties).distinguishedname
$members = Find-Members $distinguishedName
write-host "Total members including nested members is $members"
}