none
Trying to list members of groups with more than 5000 RRS feed

  • Question

  • I am trying to write a script to do 3 things:

    1. Select all groups starting with "ROLE_*"

    2. For each group from 1, list all members

    3. Write to file.

    I have been using this, which works well until it hits a group with more than 5000 members:

    Import-Module ActiveDirectory
    
    $Groups = (Get-AdGroup -filter * | Where {$_.name -like "ROLE_*"} | select name -expandproperty name)
    
    $Table = @()
    
    $Record = [ordered]@{
    "Group Name" = ""
    "Name" = ""
    "Username" = ""
    }
    
    
    Foreach ($Group in $Groups)
    {
    
    $Arrayofmembers = Get-ADGroupMember -identity $Group | select name,samaccountname
    
    foreach ($Member in $Arrayofmembers)
    {
    $Record."Group Name" = $Group
    $Record."Name" = $Member.name
    $Record."UserName" = $Member.samaccountname
    $objRecord = New-Object PSObject -property $Record
    $Table += $objrecord
    
    }
    
    }
    
    $Table | export-csv "C:\Users\user\Desktop\BOGroups.csv" -NoTypeInformation

    Unfortunately, this only works on groups that have 5000 or less members. When run against larger groups, I get this error:

    Get-ADGroupMember : The size limit for this request was exceeded
    At line:19 char:19
    + $Arrayofmembers = Get-ADGroupMember -identity $Group | select name,samaccountnam ...
    +                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (ROLE_CSR:ADGroup) [Get-ADGroupMember], ADException
        + FullyQualifiedErrorId : The size limit for this request was exceeded,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember

    Since I am only interested in users who are active, I thought limiting the results to only accounts that are not disabled might reduce the number below 5000... but I do not know how to do that. Any ideas?

    I am also open to other/better ways to accomplish this, if anyone has suggestions.

    Thanks.


    Tuesday, April 4, 2017 5:40 PM

All replies

  • I am only aware of a work around.  Run this with the values you need and export-cvs
    (Get-ADGroup -Identity $Group -Properties Members).Members | Get-ADUser | Select-Object name,samAccountName | Export-Csv u:\groupmembers.csv

    Tuesday, April 4, 2017 5:47 PM
  • Also, Get-ADGroup and Get-ADGroupMember both require that the group be identified by one of the following: distinguishedName, sAMAccountName, SID or GUID. Your code assumes that Name (the common name of the group) is the same as the sAMAccountName. Might be best to substitute sAMAccountName for Name, which in general does not uniquely identify the object in AD.

    As for only considering users that are enabled, the truth is that the group members could be computers, groups, contacts (which have no sAMAccountName), or users. But more importantly, we cannot retrieve the status of the user until after we retrieve the member values. This would require another step to determine if the user is enabled, but if Get-ADGroupMember can only retrieve 5000 objects, it does not help. There is no way to filter members in the Get-ADGroupMember cmdlet.

    If you are restricting the results to enabled users, perhaps the solution is to use Get-ADUser and filter on users that are both enabled and members of each group.

    Edit: Not tested, but something like this should work and avoid the 5000 member limit:

    $Groups = Get-ADGroup -filter {Name -like "ROLE_*"}
    
    Foreach ($Group in $Groups)
    {
        $ArrayOfMembers = Get-ADUser -Filter {(Enabled -eq $True) -And (memberOf -eq $($Group.distinguishedName))} | Select Name, sAMAccountName
        ForEach ($Member in $ArrayOfMembers)
        {
            $Record."Group Name" = $Group.Name
            $Record."Name" = $Member.Name
            $Record."UserName" = $Member.sAMAccountName
            $objRecord = New-Object PSObject -property $Record
            $Table += $objrecord
        }
    }

    Notice I filter in the Get-ADGroup cmdlet, rather than piping to a Where clause. I retrieve all default properties of the groups, because I need the distinguishName to compare to the memberOf attribute of the users. The Get-ADUser cmdlet supports the Enabled property. The drawback is that this only reveals direct group membership. This will not reveal nested group membership, or membership in the "primary" group of the users (which should be "Domain Users" for everyone).


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)






    • Marked as answer by Joe Rella Tuesday, April 4, 2017 7:16 PM
    • Unmarked as answer by Joe Rella Tuesday, April 4, 2017 7:16 PM
    • Edited by Richard MuellerMVP Tuesday, April 4, 2017 11:00 PM fixed code
    Tuesday, April 4, 2017 6:19 PM
  • This is a drawback of the cmdlet Get-Adgroupmember, it can’t fetch the report of any group which exceeds more than 1500 users. A way to fetch the report is using the below syntax.
     

    (Get-ADGroup -Identity BrassRing -Properties Members).Members

    The output of above piece of code is the list of distinguishedName of the users. You can get the name and SamAccountname of those users by passing the output using pipeline to Get-ADUser cmdlet.

    Tuesday, April 4, 2017 6:26 PM
  • Richard - I tried your suggestion and got this:

    Get-User : The term 'Get-User' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the 
    path is correct and try again.
    At line:5 char:23
    +     $ArrayOfMembers = Get-User -Filter {(Enabled -eq $True) -And (memberOf -eq $ ...
    +                       ~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (Get-User:String) [], CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException

    So I changed "Get-User" to "Get-ADUser" and got the following:

    Get-ADUser : Cannot process argument because the value of argument "path" is not valid. Change the value of the "path" argument and run the operation again.
    At line:5 char:23
    +     $ArrayOfMembers = Get-ADUser -Filter {(Enabled -eq $True) -And (memberOf -eq ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [Get-ADUser], PSArgumentException
        + FullyQualifiedErrorId : Cannot process argument because the value of argument "path" is not valid. Change the value of the "path" argument and run the operation again.,Microsoft.ActiveDir 
       ectory.Management.Commands.GetADUser

    Any ideas?



    • Edited by Joe Rella Tuesday, April 4, 2017 6:57 PM
    Tuesday, April 4, 2017 6:53 PM
  • Sorry, it is obviously Get-ADUser. I will correct my post. I apologize.

    Edit: I have been researching your error message when you use Get-ADUser, but cannot make sense out of it. The Get-ADUser cmdlet does not support a "Path" parameter. I found a few cases where people reported this error message, but found no explanation or fix.

    What I would try is to not pipe the Get-ADUser statement to the Select clause. It adds very little and may be altering the nature of the object $ArrayOfMembers. Just a guess, until I can test. The new line in the script would be:

    $ArrayOfMembers = Get-ADUser -Filter {(Enabled -eq $True) -And (memberOf -eq $($Group.distinguishedName))}


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)



    Tuesday, April 4, 2017 11:00 PM
  • No, first of all thank you for your post. Second, I was not correcting you, just noting what happened when I changed it to Get-ADUser and I was hoping you might have some more guidance on the resulting error.

    Thank you for making the edit to the code. I just tried the edited code and got this:

    Get-ADUser : Cannot process argument because the value of argument "path" is not valid. Change the value of the "path" argument and run the 
    operation again.
    At line:5 char:23
    +     $ArrayOfMembers = Get-ADUser -Filter {(Enabled -eq $True) -And (memberOf -eq ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [Get-ADUser], PSArgumentException
        + FullyQualifiedErrorId : Cannot process argument because the value of argument "path" is not valid. Change the value of the "path" argument  
       and run the operation again.,Microsoft.ActiveDirectory.Management.Commands.GetADUser

    Any ideas? It seems like it's getting closer.

    Thanks again.


    • Edited by Joe Rella Wednesday, April 5, 2017 1:02 AM
    Wednesday, April 5, 2017 12:42 AM
  • Tried with the new line, same error. I really appreciate your help.
    Wednesday, April 5, 2017 1:06 AM
  • I managed to test in my test domain. I never got your error message, but then it never helped anyway. The following, in part, worked for me:

    $Groups = Get-ADGroup -filter {Name -like "ROLE_*"}
    
    Foreach ($Group in $Groups)
    {
        $GroupDN = $Group.distinguishedName
        $ArrayOfMembers = Get-ADUser -Filter {(Enabled -eq $True) -And (memberOf -eq $GroupDN)} | Select Name, sAMAccountName
        ForEach ($Member in $ArrayOfMembers)
        {
            $Record."Group Name" = $Group.Name
            $Record."Name" = $Member.Name
            $Record."UserName" = $Member.sAMAccountName
            $objRecord = New-Object PSObject -property $Record
            $Table += $objrecord
        }
    }


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)


    Wednesday, April 5, 2017 1:43 AM
  • Interesting... I get the following when I run this:

    The property 'Group Name' cannot be found on this object. Verify that the property exists and can be set.
    At line:9 char:9
    +         $Record."Group Name" = $Group.Name
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : PropertyNotFound
     
    The property 'Name' cannot be found on this object. Verify that the property exists and can be set.
    At line:10 char:9
    +         $Record."Name" = $Member.Name
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : PropertyNotFound
     
    The property 'UserName' cannot be found on this object. Verify that the property exists and can be set.
    At line:11 char:9
    +         $Record."UserName" = $Member.sAMAccountName
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : PropertyNotFound
     
    Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named 'op_Addition'.
    At line:13 char:9
    +         $Table += $objrecord
    +         ~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (op_Addition:String) [], RuntimeException
    Wednesday, April 5, 2017 2:23 PM
  • > Interesting... I get the following when I run this:
     
    You missed the "in partial" statement of Richard. He has some surrounding code that creates a table and some records :-)
     
    Here's not the place to get "solutions ready for production", but rather "tips how to create your own solution".
     
    Thursday, April 6, 2017 1:28 PM
  • Yes, I did not include the lines where you defined the $Record hash table. Sorry. I only included the portion I modified.

    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Thursday, April 6, 2017 3:47 PM
  • My most sincere apologies... I thought I made it clear that I was attempting to solve a very specific issue, not learn how to code in powershell.

    Thanks for this very informative post.
    Friday, April 7, 2017 2:56 PM
  • Thanks for your assistance Richard; I will find a different way to do this. I do not have coding/scripting experience, so need very specific details... as you have by now realized. Apologies for taking up your time.
    Friday, April 7, 2017 3:03 PM
  • Try this one I published in the gallery:

    https://gallery.technet.microsoft.com/scriptcenter/Get-ADGroupMemberAttributep-2663d468

    It uses a "paged search" and thus doesn't have a limit to the number of group members it can retrieve.

    You have to provide it a distinguished name for the group, but it does support the pipeline.


    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Bill_Stewart Tuesday, May 23, 2017 2:27 PM
    Friday, April 7, 2017 4:27 PM