Working with hash of arrays

Welcome Forums General PowerShell Q&A Working with hash of arrays

Viewing 5 reply threads
  • Author
    Posts
    • #171190
      Participant
      Topics: 1
      Replies: 3
      Points: 18
      Rank: Member

      Hi,

      I'm new to powershell, and having a bit of trouble with my first script. I'm pulling group memberships from AzureAD users (as a list of groups per each member) and wish to format as a list of members per each group. So my method was to create a hash of arrays, with groups as a key, and its members as an array value. Here's what I have:

      
      # list of users by userPrincipalName
      $upns = @('moe@stooge.com', 'larry@stooge.com', 'curly@stooge.com')
      
      $users = New-Object System.Collections.ArrayList
      $groupMemberships = @{}
      
      # Convert userPrincipalName to User Object
      ForEach ($upn in $upns) {
      if ( $user = Get-AzureADUser -Filter "userPrincipalName eq '$upn'" ) {
      $users += $user
      }
      }
      
      # Collect membership for each seen group
      ForEach ( $user in $users ) {
      ForEach ( $seenGroup in Get-AzureADUserMembership -All $true -ObjectID $user.ObjectId ) {
      if ( $groupMemberships.ContainsKey( $seenGroup ) ) {
      $groupMemberships[ $seenGroup ] += $user
      } else {
      $groupMemberships[ $seenGroup ] = @();
      $groupMemberships[ $seenGroup ] += $user
      }
      }
      }
      
      

      My problem is in pushing users into the hash of arrays. If the hash key doesn't exist, I create a new empty array as the hash value, then add the user to it. Problem is that all of the resulting hashes only contains a single user in the array – I'm not able to detect the  resulting hash key "if ( $groupMemberships.ContainsKey( $seenGroup )",  so with each iteration (over groups), a new array is created, deleting the previous array.

      I suspect I am having issues with scope, but not sure how to fix it.

       

      Thanks for your help,

      Rick

    • #171205
      Participant
      Topics: 9
      Replies: 427
      Points: 711
      Helping Hand
      Rank: Major Contributor

      If the purpose of the script is to get "list of members per each group" you can use something like:

      $UPNList = @(
          'moe@stooge.com'
          'larry@stooge.com'
          'curly@stooge.com'
      )
      
      $myOutput = foreach ($UPN in $UPNList) {
          if ($AzureADUser = Get-AzureADUser -Filter "UserPrincipalName eq '$UPN'") {
              if ($GroupList = Get-AzureADUserMembership -All $true -ObjectID $AzureADUser.ObjectId) {
                  [PSCustomObject]@{
                      UPN = $UPN
                      GroupList = $GroupList.DisplayName
                  }
              }
          }
      }
      
      $myOutput
      

      I don't think a hash table of arrays is the data structure you need here.
      I recommend that you format your output as a PS Object as shown above.

    • #171220
      Participant
      Topics: 1
      Replies: 3
      Points: 18
      Rank: Member

      Hi Sam,

      Thanks for your reply, much appreciated. However I am looking for the opposite output:

      
      group1  {user1, user...}
      
      group... {user1, user...}
      
      

      Which is what I meant by "list of users in each group".

      The hash structure is useful because the same directory can appear multiple times across the users. Placing each directory as a hash key naturally combines each unique directory data into a single instance (because keys have to be unique).

      Why won't my test for a key (my line 18) find an occurence generated (my line 22) in a previous loop?

      Rick

    • #171259
      Participant
      Topics: 1
      Replies: 3
      Points: 18
      Rank: Member

      Working script below. Returns a hash, with group display names as keys, and an array of group members (user principal names) as values.

      
      $UPNList = @(
          'moe@stooge.com'
          'larry@stooge.com'
          'curly@stooge.com'
      )
      
      $users = New-Object System.Collections.ArrayList
      $groupMemberships = @{}
      
      # Convert userPrincipalName to User Object
      ForEach ($UPN in $UPNList) {
          if ( $user = Get-AzureADUser -Filter "userPrincipalName eq '$UPN'" ) {
              $users += $user
          }
      }
      
      # Collect membership for each seen group
      ForEach ( $user in $users ) {
          ForEach ( $seenGroup in Get-AzureADUserMembership -All $true -ObjectID $user.ObjectId ) {
              $displayName = $seenGroup.DisplayName
              $userPrincipalName = $user.UserPrincipalName
              if ( $groupMemberships[ $displayname ] ) {
                  $groupMemberships[ $displayName ] += $userPrincipalName
              } else {
                  $groupMemberships[ $displayName ] = @( $userPrincipalName )
              }
          }
      }
      
      $groupMemberships | Format-List
      
    • #171286
      Participant
      Topics: 9
      Replies: 427
      Points: 711
      Helping Hand
      Rank: Major Contributor
      $UPNList = @(
          'moe@stooge.com'
          'larry@stooge.com'
          'curly@stooge.com'
      )
      
      $UserGroupMembership = foreach ($UPN in $UPNList) {
          if ($AzADUser = Get-AzureADUser -Filter "UserPrincipalName eq '$UPN'") {
              if ($GroupList = Get-AzureADUserMembership -All $true -ObjectId $azAdUser.ObjectId) {
                  [PSCustomObject]@{
                      UPN       = $UPN
                      GroupList = $GroupList.DisplayName
                  }
              }
          }
      }
      
      $GroupUserMembership = foreach ($GroupName in ($UserGroupMembership.GroupList | select -Unique)) {
          [PSCustomObject]@{
              GroupName  = $GroupName
              MemberList = ($UserGroupMembership | where GroupList -Contains $GroupName).UPN
          }
      }
      
      $UserGroupMembership | FT -a 
      $GroupUserMembership | FT -a
      
    • #171301
      Participant
      Topics: 1
      Replies: 3
      Points: 18
      Rank: Member

      Hs Sam,

      Very elegant. Looks like I should  learn more about PSCustomObject and how it's used in PowerShell scripting.

      Thanks!

      Rick

Viewing 5 reply threads
  • The topic ‘Working with hash of arrays’ is closed to new replies.