0

I found this function I'd like to use in a script I'm writing, but it keeps coming back $false when I can see an account is in a group and I can't figure out why?

function Check-IsGroupMember{ Param($user,$grp) $strFilter = "(&(objectClass=Group)(name=" + $grp +"))" $objDomain = New-Object System.DirectoryServices.DirectoryEntry $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objSearcher.SearchRoot = $objDomain $objSearcher.PageSize = 1000 $objSearcher.Filter = $strFilter $objSearcher.SearchScope = "Subtree" $colResults = $objSearcher.FindOne() $objItem = $colResults.Properties ([string]$objItem.member).contains($user) } Usage: Check-IsGroupMember "name of user" "DomainAdmins" 
5
  • Is the group that user's primary group? Commented Oct 30, 2015 at 21:06
  • Probably not, but I was hoping to use this for any type of group? Commented Oct 30, 2015 at 21:16
  • Looking closer, it seems like the way you're doing it would work anyway, I think (searching the group's member list for a user rather than looking at the member of property of the user). Commented Oct 30, 2015 at 21:18
  • Are you using the user's name as it would appear in their Distinguished Name when you search? The results from that search are a collection of the member's distinguishedname strings, so you'd have to search for something that would appear within that. Commented Oct 30, 2015 at 21:39
  • Hmm, yes DN seems to work, but seems to come back false on a very large group we have called AllUsers (22k) should I increase the pagesize? Commented Oct 30, 2015 at 21:48

1 Answer 1

1

$objItem.member contains the DistinguishedName value of each principal who is a member of the group.

Even though the proper name of a person might be John Doe, the common name of the user account object may still be Doe, John, John G. Doe or anything else. This means that Contains() check (which is just a simple substring search) is not guaranteed to work as you expect.

The only real way to check is to either run another search for the user to find his/her DistinguishedName.

Personally, I would go for the AD PowerShell module from RSAT, rather than using a DirectorySearcher:

function Test-GroupMembership { Param( [string]$UserName, [string]$GroupName ) $User = Get-ADUser -Identity $UserName $Group = Get-ADGroup -Identity $GroupName -Properties member $Group.member -contains $User.DistinguishedName } 

If size limit is your problem, you can use the DirectoryServer to retrieve a ranged result of the member attribute:

function Test-GroupMembership { [CmdletBinding()] Param( [string]$UserName, [string]$GroupName ) # Fetch User $User = Get-ADUser -Identity $UserName # return on failure if(-not $User){ Write-Error -Message ('User "{0}" not found' -f $GroupName) return $false } # Use DirectorySearcher to retrieve ranged member attribute $GroupSearcher = '' -as [adsisearcher] $GroupSearcher.Filter = '(&(objectClass=group)(name={0}))' -f $GroupName $GroupSearcher.SearchScope = 'Subtree' $GroupSearcher.SearchRoot = '' -as [adsi] # AD reponds with at least 1500 values per multi-value attribute since Windows Server 2003 $Start = 1 $Range = 1500 $GroupMembers = @() $HasMoreMembers = $false # Keep retrieving member values until we've got them all do{ # Use range operator to "page" values # Ref: https://msdn.microsoft.com/en-us/library/aa367017(v=vs.85).aspx $RangedMember = 'member;range={0}-{1}' -f $Start,$($Start + $Range - 1) $GroupSearcher.PropertiesToLoad.Add($RangedMember) | Out-Null # Retrieve group $Group = $GroupSearcher.FindOne() # return on failure if(-not $Group) { Write-Error -Message ('Group "{0}" not found' -f $GroupName) return $false } # If we've reached the end of the member list, # AD will return a property where the upper range # value is *, so it might not be the same property # name we specified in PropertiesToLoad $ReturnedMember = @($Group.Properties.PropertyNames) -like 'member;*' # Add all members to the $GroupMembers variable foreach($member in $Group.Properties."$ReturnedMember") { # Test if user is in the member list if($member -eq $User.DistinguishedName){ return $true } } # If we've reached the end, exit the loop if($ReturnedMember -eq $RangedPropertyName){ $HasMoreMembers = $true } } while ($HasMoreMembers) # User wasn't found return $false } 

To provide a bit of consistency in user experience, please use Approved Verbs for command names in PowerShell (eg. Test-* instead of Check-*)

[adsisearcher] is a type accelerator for the DirectorySearcher class

Sign up to request clarification or add additional context in comments.

6 Comments

I'm not sure I understand? Is there a way to guarantee the function finds a specific user that in a specific group you're searching for?? I'm trying the DN and SamAccountName and groups I know my account is in or not in and getting very inconsistent results.
@MarcGel Updated the answer. I still find this approach sub-optimal though. Is there a reason you're not using the RSAT Active Directory PowerShell Module (Get-ADUser, Get-ADGroup etc.)?
I'd use those if it were not for the size limits. So, are you adding another function then for the distinguished name? Then possibly combine the functions? What is the most optimal solution? Thanks
@MarcGel if the size limit is the issue here, non of the above will work, you'll need to use the range operator
Thanks a bunch Mathias! Your Test-GroupMembership function seems to work on even our very large groups. Why do these cmdlets work in a function but not outside of one? At least it seems that way as I've gotten "Reached Max Size Limit" errors on those before?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.