4

I am stuck trying to figure out how to get all Active Directory groups that are empty. I came up with this command, which selects groups that have no Members and aren't a MemberOf anything.

Get-QADGroup -GroupType Security -SizeLimit 0 | where-object {$_.Members.Count -eq 0 -and $_.MemberOf.Count -eq 0} | select GroupName, ParentContainer | Export-Csv c:\emptygroups.csv

This is mostly correct, but it's saying certain groups like the default group Domain Computers is empty, but it isn't empty. This particular group has only members that are computers, but it appears that other groups that only have computers as well aren't selected.

Does anyone know why this command is pulling in some that have members?

Kirk
  • 16,182
  • 20
  • 80
  • 112

6 Answers6

5

The Get-QADGroup cmdlet has a parameter -Empty. The description in the help hints at the reason these default groups are being returned:

Note: A group is considered empty if it has the "member" attribute not set. So, this parameter can retrieve a group that has only those members for which the group is set as the primary group. An example is the Domain Users group, which normally is the primary group for any user account while having the "member" attribute not set.

I'm not really familiar with the Quest stuff, but I was able to find empty groups this way, (probably not the most efficient):

Get-ADGroup -Filter {GroupCategory -eq 'Security'} | ?{@(Get-ADGroupMember $_).Length -eq 0}
badgerious
  • 98
  • 3
  • Thank you for the answer. The problem I run into with using `Get-ADGroupMember` is that it errors with _The size limit for this request was exceeded_ on large groups and seems to return those are having no members. For example **Domain Users** which has nearly 15,000 members. Any idea on that? – Kirk Aug 14 '12 at 16:19
  • 1
    Indeed, I tried that on a test domain controller with very few users and sort of suspected something would go wrong in a live environment. Like your later response, it looks like `Get-QADGroupMember` is the way to do it. I might suggest setting `-SizeLimit 1` (probably want `-WarningAction SilentlyContinue` with that) for the `Get-QADGroupMember` calls since you only need one to determine if it is empty or not. – badgerious Aug 14 '12 at 18:04
  • Good suggestion with `-SizeLimit 1`. – Kirk Aug 14 '12 at 18:15
5

This line will do (use Import-Module ActiveDirectory first):

Get-ADGroup -Filter * -Properties Members | where { $_.Members.Count -eq 0 }
Massimo
  • 1,520
  • 1
  • 19
  • 36
  • This is working for me but I'm getting some false positives, like Domain Users is showing up which obviously isnt empty. – JoeRod Jan 04 '16 at 16:43
1

This version will display only the groupcategory and SAMaccountname. Name could also be used in place of samaccountname. The groupcategory will show you if its a security group or a DL.

Get-ADGroup –Filter * -Properties Members | where { $_.Members.Count –eq 0 } |select groupcategory,samaccountname >c:\temp\nomembers.csv
gizzle
  • 11
  • 1
1

Actually it will be a lost faster in environments with multiple domains, large number of groups (and large number of users) to run it as a script. Note: you will need to have PowerShell Active directory module loaded (import-module activedirectory)

     $domains = Get-ADForest|select -ExpandProperty domains
     $empties = @()
     $oops = @()
     foreach ($d in $domains){
     $groups = get-adgroup -filter * -server $d
     foreach ($g in $groups){
     $q = get-adgroup $g -properties members -server $d|select -expandproperty members
     If(!$?){$oops += $g
     write-host $g.name}
     if ($q -eq $null) {$empties += $g}
     }
     }
     $empties|select name,distinguishedname|export-csv .\empties.csv
     $oops|select name,distinguishedname|export-csv .\oops.csv
1

This worked for me.

Get-ADGroup -Filter {GroupCategory -eq 'Security'} -Properties Members | where { $_.Members.Count -eq 0 } | Select Name | Sort-Object Name
Alex Myers
  • 6,196
  • 7
  • 23
  • 39
Andrew
  • 11
  • 1
0

Was able to get the values properly by piping in Get-QADGroupMember and getting the count of Members and MemberOf which could then be filtered. This seems terribly inefficient, but it serves the purpose to get the counts needed.

Get-QADGroup -SizeLimit 0 | Select-Object Name,@{n='MemberCount';e={ (Get-QADGroupMember $_ -SizeLimit 0 | Measure-Object).Count}},@{n='MemberOfCount';e={ ((Get-QADGroup $_).MemberOf | Measure-Object).Count}}

If anyone has a better way to do this, do tell.

Kirk
  • 16,182
  • 20
  • 80
  • 112