Search code examples
powershellssisactive-directoryldapactive-directory-group

Extract all users from active directory groups from multiple domains using Powershell?


I don't have much expertise in Active Directory or Powershell, I need to pull all users and there details belonging to over 1000 security groups.

I've tried few different PS scripts available online but due to the large amount of data the script is taking a really long time to complete (I stopped the script after it kept running for 3 days)

I also tried breaking down the group list and running 100 groups at a time using SSIS but no avail.

I'm using the following 1st script to pull the members of the groups and the 2nd script to pull the rest of the user details

P.S. the groups and users are a mix from multiple sub-domains.

Script 1:

$groups = Get-Content c:\temp\Groups.txt      
foreach($Group in $Groups) {            
    Get-ADGroupMember -Id $Group | select  @{Expression=    {$Group};Label="Group Name"},* | Export-CSV c:\temp\GroupsInfo.CSV -    NoTypeInformation
}

Script 2:

$objForest =     [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$DomainList = @($objForest.Domains | Select-Object Name)
$Domains = $DomainList | foreach {$_.Name}
$Users = Import-CSV c:\users\public\users.csv
#Act on each domain
foreach($Domain in ($Domains))
{
    Write-Host "Checking $Domain" -fore blue
    Foreach($mail in ($Users.mail))
    {
        Get-ADUser -filter {mail -eq $mail} -Server $domain -properties     mail | select mail,employeeID,title,department,name

        Export-CSV c:\temp\MemberDetails.CSV -NoTypeInformation
    }
}

Solution

  • ran this against a group with 4300+ members

    it took a couple minutes

    $groupname = <whatever your group name is>
    $servername = <whatever domain your group is with>
    
    $dns = get-adgroup $groupname -server $servername -Properties member | select -ExpandProperty member
        $adobjects = @()
        $objqry = {
            param([string[]]$items)
            function GetAdsiObj {
                param($dn)
                $item = [adsi]$("LDAP://$_")
                $item.setinfo()
                return $item
            }
            return $items | select @{n='adsiobj';e={ GetAdsiObj $_}} | `
                select @{n='samaccountname';e={$_.adsiobj.properties.samaccountname[0]}}, `
                       @{n='name';e={$_.adsiobj.properties.name[0]}}, `
                       @{n='objectclass';e={$_.adsiobj.properties.objectclass[$_.properties.adsiobj.objectclass.count - 1]}}, `
                       @{n='dn';e={$_.adsiobj.path}}, `
                       @{n='useraccountcontrol';e={$_.adsiobj.useraccountcontrol[0]}}
        }
        $jobs = @()
    
        for($i= 0; $i -lt $dns.Count;$i += 250){
            $data = $dns[$i..$($i + 249)] 
            $jobs += Start-Job -ScriptBlock $objqry -ArgumentList (,$data)
        }
    
        $runningcount = {
            param($j)
            return $($j | ?{ $_.State -eq "Running" }).Count
        }
        $jobcount = $jobs.Count
        while($(&$runningcount $jobs) -gt 0){
            write-progress -activity "Processing members" -status "Progress:" `
            -percentcomplete (($jobcount- $(&$runningcount $jobs))/$jobcount*100)
        }
        $responses = $jobs | Wait-Job | Receive-Job
        $responses | %{ $adobjects += @($_) }
        $adobjects