none
Why is Get-ADGroupMember so slow? RRS feed

  • General discussion

  • I tried to write a script that does some AD stuff, and the script took like half an hour to run when I expected it to take maybe half a minute. I debugged the whole thing and found out that the Get-ADGroupMember cmdlet is taking up 99% of that runtime.

    I write the following script to test this and compare the Powershell method with the .NET one:

    $domain = "domain.local"
    $groupname = "SomeGroup"
    
    $start = Get-Date
    $group1 = Get-ADGroupMember $groupname
    "With Get-ADGroupMember " + ((Get-Date) - $start).TotalMilliseconds
    
    
    $start = Get-Date
    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    $pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain, $domain)
    $group2 = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($pc, [System.DirectoryServices.AccountManagement.IdentityType]::Name, $groupname)
    #$group2.Members.GetEnumerator() | % { $_.DisplayName }
    "With .NET " + ((Get-Date) - $start).TotalMilliseconds

    If I use that on a group with 7 members, Powershell takes 1.7 seconds (!) to run while the native .NET does it in 13 milliseconds.

    If I try a group with 300 members, Powershell takes 52 seconds and .NET 18 milliseconds.

    Does anyone know if it's possible to get Powershell to improve on that? Because right now I'm tempted to homebrew my own cmdlet based on .NET.

    Friday, June 10, 2016 2:26 PM

All replies

  • You searched before asking, right?

    http://www.google.com/search?&q=get-adgroupmember+slow


    -- Bill Stewart [Bill_Stewart]

    Friday, June 10, 2016 2:30 PM
    Moderator
  • Yep and one of the result mentions that I need to import the ActiveDirectory module (very helpful!) while others mention nonexisting SIDs (I don't have any) or recursive search (which I don't do).

    I'm trying to do a straight up nonrecursive linear list in a one-domain forest to a local domain controller but it still takes forever.

    Friday, June 10, 2016 2:38 PM
  • Yes it is slower as startup takes more time:

    Here is an easier way to do timings.

    Add-Type -AssemblyName System.DirectoryServices.AccountManagement
    
    Measure-Command {Get-ADGroupMember 'Domain Users' }
    
    Measure-Command {
    	$domain='kahlnet'
    	$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain, $domain)
    	$group2 = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($pc, [System.DirectoryServices.AccountManagement.IdentityType]::Name, $groupname)
    	$group2.Members.GetEnumerator() | % { $_.DisplayName }
    }
    Account Management was not available when the AD CmdLets were created.  It was only added in Net 3.5.


    \_(ツ)_/



    • Edited by jrv Friday, June 10, 2016 2:55 PM
    Friday, June 10, 2016 2:53 PM
  • Right, so we have the same access to information that you have.

    Not sure what other insight we can offer regarding your question.


    -- Bill Stewart [Bill_Stewart]

    Friday, June 10, 2016 4:16 PM
    Moderator