I’m having a PowerShell syntax issue: I can’t seem to match members of one array to another array, but I can confirm the members exist in both arrays. Can someone point out my logic error?
Background:
I want to search Entra for all members of a specific group, based on a search string of the member’s properties (e.g. DisplayName and Surname). Given limitations to the Get-Mg* -filter calls, I’ve come up with this approach:
$groupName = 'staff' # all results should be in staff group
$userMatchString = 'Be' # e.g. [Be]n Smith, Jim [Be]am...
$domainMatch = 'example.com' # custom domain - no Entra guests
## choose a central M365 group filter
$group = get-mggroup -Filter "DisplayName eq '$($groupName)'"
$groupMemberIds=Get-MgGroupMember -GroupId $group.id -ConsistencyLevel eventual -All | select Id
## find Entra users matching a search string
## Due to graph filter limitations we do separate calls per attribute
$userMatches=@(Get-MgUser -ConsistencyLevel eventual -Count userCount -Filter "startsWith(DisplayName, '$($userMatchString)')" | where { $_.Mail -like "*@$($domainMatch)"})
$userMatches+=@(Get-MgUser -ConsistencyLevel eventual -Count userCount -Filter "startsWith(Surname, '$($userMatchString)')" | where { $_.Mail -like "*@$($domainMatch)" })
At this point $groupMemberIds
contains every qualifiable person to search for and $userMatches
contains every Entra search result (that may or may not be in the group).
This confirms (for my resultset) that the first record is already a match: $groupMemberIds | where { $_.Id -eq $userMatches[0].Id }
Can someone help me with syntax for (any userMatches ) in (groupMemberIds)?
This doesn’t work – it returns ‘false’ for all of them:
$userMatches | ForEach-Object { $($_.Id -in $groupMemberIds) }
Any ideas? Thanks!
UPDATE:
With my code I’m apparently comparing string to PSCustomObject… trying to figure out how to compare these as apples to apples…
$userMatches[0].Id.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
$groupMemberIds[0].gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
4
Answers
In order to compare these apples to apples, I need to specify the
.id
property of the array members versus the array members themselves.This version with
$groupMemberIds.id
is returning matches, as it is now a String comparison:I’m unsure as to which limitation you’re referring to but what it seems you’re looking to achieve is certainly doable through the OData filter. I’m not sure if you can do it with the
Get-MgGroupMember
cmdlet but usingInvoke-MgGraphRequest
you can do:There’s a much easier approach. When you use
Get-MgGroupMember
you will retrieve all the user properties you need to do your filtering. But your script is stripping these values when you pipe your output to| Select id
.You can do it like this:
Although my other answer solves the root question I had (comparing the arrays), this alternate answer is arguably a more efficient way to compare the results. Kudos to Architect Jamie and Santiago Squarzon for their help!
Full example: