Assen Antonov
Assen Antonov

Reputation: 15

PowerShell: Trying to find which users are not members of a list of groups

In our organization we have job title groups for multiple reasons and I'm trying to find which users have no group assigned. The groups and users are stored in the same OU in AD. There are groups for the departments containing "department" in the title, so I'm excluding those, as they are nesting all the job title groups for a department, and there are no users, which are direct members. This is what I came up with so far, but sometimes I receive duplicate results like the function is running several times against the same entry and I don't understand why.

cls
$SearchBase = "OU DN"
$ErrorActionPreference = "Continue"
$Groups = Get-ADGroup -SearchBase $SearchBase -Filter 'Name -notlike "*department*"' | Select -ExpandProperty Name
$Users = Get-ADUser -SearchBase $SearchBase -Filter * | Select -ExpandProperty Name | sort
$TotalItems = $Users.Count
$CurrentItem = 0
$PercentComplete = 0

function Get-JTGroups($User) {
    foreach ($Group in $Groups) {
        $int = 0
        Try {
            $Members = Get-ADGroupMember -Identity "$Group" -Recursive | Select -ExpandProperty Name -ErrorAction Stop
        }
        Catch {
            Write-Host $_.Exception.Message
        }
        
        if ($Members -contains $User) {
            $int = 1
            Write-Host "$User has JT group"
        }
    }

    if ($int = 0) {
        Write-Host "$User has no JT group"
    }
}

foreach ($User in $Users) {
    Write-Progress -Activity "Checking JT Groups members, hold on." -Status "$PercentComplete% Complete:" -PercentComplete $PercentComplete
    Get-JTGroups $User
    $CurrentItem++
    $PercentComplete = [int](($CurrentItem / $TotalItems) * 100)
}

Is there a way to avoid duplicated entries and can this code be optimized?

Thanks in advance

Upvotes: 1

Views: 410

Answers (1)

Santiago Squarzon
Santiago Squarzon

Reputation: 59781

I believe this task would be easier, faster and more efficient by leveraging the filtering capabilities of Active Directory. Your current code as is will be tremendously slow because you're getting the recursive membership of all the groups in $groups for each user in $users. Instead you can ask AD to find all users who are not a recursive member of any of the groups in $groups.

$filter = '(&'
Get-ADGroup -SearchBase $SearchBase -Filter 'Name -notlike "*department*"' | ForEach-Object {
    $filter += '(!memberOf:1.2.840.113556.1.4.1941:={0})' -f $_.DistinguishedName
}
$filter += ')'
$allUsersNotRecursiveMemberofGroups = Get-ADUser -LDAPFilter $filter

For details on LDAP Filter see Active Directory: LDAP Syntax Filters.

Upvotes: 0

Related Questions