how to catch the exceptions

Welcome Forums General PowerShell Q&A how to catch the exceptions

Viewing 19 reply threads
  • Author
    Posts
    • #218781
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      Hi ,

      I’ve got this code which should remove the user from all the groups a user is member of in azureAD.
      Some of the groups I can’t remove due to restrictions which result in this type of error messages
      Remove-AzureADGroupMember : Error occurred while executing RemoveGroupMember
      Code: Request_BadRequest
      Message: Unable to update the specified properties for objects that have originated within an external service.
      RequestId: fc9382f2-4441-417e-a6e1-bb3bd05ef9d1
      DateTimeStamp: Wed, 15 Apr 2020 06:11:45 GMT
      HttpStatusCode: BadRequest
      HttpStatusDescription: Bad Request
      HttpResponseStatus: Completed
      At line:9 char:34
      + … oupMember = Remove-AzureADGroupMember -ObjectId $group.objectID -Memb …
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : NotSpecified: (:) [Remove-AzureADGroupMember], ApiException
      + FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.RemoveGroupMember

      My question is how do I catch these errors so that these are not shown on the screen. can this be put in an error log?
      my code is

      
      #connect to azureAD
      Connect-AzureAD
      #read file with users (email address)
      $users = import-csv c:\temp\toRemove.csv
      
      foreach ($user in $users) {
      #get the users objectID from Azure
      $UserObjectID =get-AzureAdUser -objectId $user.SamAccountName |select objectID
      #grab the clean objectID from the user
      $SelectUserObjectID= $userObjectID.objectID
      #find all the groups a user is member off
      $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $SelectUserObjectID
      
      foreach ($group in $UserObjectIDGroupMemberShip) {
      #remove the user from each indivudual group
      $removeAzureAdGroupMember = Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID
      }
      }
      

      thanks Paul

    • #218796
      Participant
      Topics: 4
      Replies: 2231
      Points: 5,414
      Helping Hand
      Rank: Community MVP

      Did you consider implementing some error handling with try catch?

      Get-Help about_try_catch_finally
    • #218841
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      thanks for the tip

       

    • #218880
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      if someone is interested here’s the final working script

      
      #connect to azureAD
      Connect-AzureAD
      #read file with users (email address)
      $users = import-csv c:\temp\toRemove.csv
      $ErrorLog = “c:\temp\groupdeletionErrors.txt”
      
      foreach ($user in $users) {
      #get the users objectID from Azure
      $UserObjectID =get-AzureAdUser -objectId $user.SamAccountName |select objectID
      #grab the clean objectID from the user
      $SelectUserObjectID= $userObjectID.objectID
      #find all the groups a user is member off
      $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $SelectUserObjectID
      
      foreach ($group in $UserObjectIDGroupMemberShip) {
      #remove the user from each indivudual group
      try {
      $removeAzureAdGroupMember = Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID
      }
      catch {
      #the groups that cannot be removed are safed in the error log
      “Error removing $group” + “:” + “$_” |Add-Content $ErrorLog
      }
      finally {
      #output on screen
      Write-host “user is removed from ” + “-” + $group.DisplayName
      }
      }
      }
      
      
      • This reply was modified 1 month, 1 week ago by acer460527.
    • #218898
      Participant
      Topics: 4
      Replies: 2231
      Points: 5,414
      Helping Hand
      Rank: Community MVP

      Great. Thanks for sharing.

      Just as an aside note: You declare the variable $removeAzureAdGroupMember but you never use it. πŸ˜‰ And you should do yourself and all others a favor and indent your code to make it easier readable. You may read the Powershell Best Practice and Style Guide.

    • #218952
      Participant
      Topics: 48
      Replies: 194
      Points: 767
      Helping Hand
      Rank: Major Contributor

      If I’m understanding try..catch..finally correctly, your script will say the user is removed whether they are or not.

      
      https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7
      
      
    • #218961
      Participant
      Topics: 24
      Replies: 172
      Points: 557
      Helping Hand
      Rank: Major Contributor

      Check out the Free Resources link on the left, in the ebooks you’ll see an entry for the big book of powershell error handling.

      Or here is the direct link

      https://leanpub.com/thebigbookofpowershellerrorhandling

    • #219039
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      Great. Thanks for sharing.

      Just as an aside note: You declare the variable $removeAzureAdGroupMember but you never use it. 😉 And you should do yourself and all others a favor and indent your code to make it easier readable. You may read the Powershell Best Practice and Style Guide.

      don’t quite understand your remark on the $removeAzureAdGroupMember because when I check the user in question the groups that can be removed are removed. concerning the the readability of the code I copy pasted it from my original powershell window and the indents are there

      • This reply was modified 1 month, 1 week ago by acer460527.
    • #219186
      Participant
      Topics: 4
      Replies: 2231
      Points: 5,414
      Helping Hand
      Rank: Community MVP

      don’t quite understand your remark on the $removeAzureAdGroupMember because when I check the user in question the groups that can be removed are removed. concerning the the readability of the code I copy pasted it from my original powershell window and the indents are there

      Unfortunately you deleted the code I was reffering to. If I remember right you had a code line like this …

      $removeAzureAdGroupMember = Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID

      So you declare a variable $removeAzureAdGroupMember but in the code you posted you never used it. That’s what I meant.

    • #219225
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      @olaf,

      I don’t understand why it got removed but here’s the code again

      
      #connect to azureAD
      Connect-AzureAD
      #read file with users (email address)
      $users = import-csv c:\temp\toRemove.csv
      $ErrorLog = “c:\temp\groupdeletionErrors.txt”
      
      foreach ($user in $users) {
      #get the users objectID from Azure
      $UserObjectID =get-AzureAdUser -objectId $user.SamAccountName |select objectID
      #grab the clean objectID from the user
      $SelectUserObjectID= $userObjectID.objectID
      #find all the groups a user is member off
      $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $SelectUserObjectID
      
      foreach ($group in $UserObjectIDGroupMemberShip) {
      #remove the user from each indivudual group
      try {
      $removeAzureAdGroupMember = Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID
      $removeAzureAdGroupMember
      }
      catch {
      #the groups that cannot be removed are safed in the error log
      “Error removing $group” + “:” + “$_” |Add-Content $ErrorLog
      }
      finally {
      #output on screen
      Write-host “user is removed from ” + “-” + $group.DisplayName
      }
      }
      }
      
      
      • This reply was modified 1 month, 1 week ago by acer460527.
      • This reply was modified 1 month, 1 week ago by acer460527.
      • This reply was modified 1 month, 1 week ago by acer460527.
    • #219243
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      here’s the code again and I’ve added the variable again however what I don’t understand at this point is why it’s working even without adding the second $removeAzureAdGroupMember

      
      #connect to azureAD
      Connect-AzureAD
      #read file with users (email address)
      $users = import-csv c:\temp\toRemove.csv
      $ErrorLog = “c:\temp\groupdeletionErrors.txt”
      
      
      
      foreach ($user in $users) {
      #get the users objectID from Azure
      $UserObjectID =get-AzureAdUser -objectId $user.SamAccountName |select objectID
      #grab the clean objectID from the user
      $SelectUserObjectID= $userObjectID.objectID
      #find all the groups a user is member off
      $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $SelectUserObjectID
      
      foreach ($group in $UserObjectIDGroupMemberShip) {
      #remove the user from each indivudual group
      try {
      $removeAzureAdGroupMember = Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID
      $removeAzureAdGroupMember
      }
      catch {
      #the groups that cannot be removed are safed in the error log
      “Error removing $group” + “:” + “$_” |Add-Content $ErrorLog
      }
      finally {
      #output on screen
      Write-host “user is removed from ” + “-” + $group.DisplayName
      }
      }
      }
      
      

      ps don’t know what is wrong with the indents but can’t get it working correctly mea culpa

      • This reply was modified 1 month, 1 week ago by acer460527.
    • #219261
      Participant
      Topics: 4
      Replies: 2231
      Points: 5,414
      Helping Hand
      Rank: Community MVP

      I don’t have access to an Azure AD ad the moment to test but I think this should do the same:

      Connect-AzureAD
      $users = import-csv c:\temp\toRemove.csv
      $ErrorLog = 'c:\temp\groupdeletionErrors.txt'
      
      foreach ($user in $users) {
          $UserObjectID = get-AzureAdUser -objectId $user.SamAccountName | Select-Object -Property objectID
          $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $($userObjectID.objectID)
      
          foreach ($group in $UserObjectIDGroupMemberShip) {
              try {
                  Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID
              }
              catch {
                  "Error removing $group : $($_)" | Add-Content $ErrorLog
              }
              finally {
                  "user is removed from - $($group.DisplayName)"
              }
          }
      }

      You should avoid to comment obvious things. If the command is Connect-AzureAD even an unexperienced Powersheller knows that this command connects to an Azure AD. πŸ˜‰ Powershell is quite self-explanatory.

      In your try block you assign the output of Remove-AzureADGroupMember to a variable. Does this cmdlet actually produce any output? I wouldn’t expect it to by default. Even if it does – you assign a variable and output this variable right away and do not use it any further. So it’s not needed at all – that’s what I meant before. πŸ˜‰

      What editor do you use to write your scripts? (Just out of my curiosity)

    • #219411
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      I use the powershell ISE editor

    • #219441
      Participant
      Topics: 4
      Replies: 2231
      Points: 5,414
      Helping Hand
      Rank: Community MVP

      I use the powershell ISE editor

      … hmm … strange … when I use the the ISE and paste some code the indentation is retained.

    • #219450
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      I use the powershell ISE editor

      … hmm … strange … when I use the the ISE and paste some code the indentation is retained.

      what do you use as editor notepad++ or a different one?

       

    • #219456
      Participant
      Topics: 4
      Replies: 2231
      Points: 5,414
      Helping Hand
      Rank: Community MVP

      what do you use as editor notepad++ or a different one?

      ISE and VSCode. Notepad++ only when I’m on a server and want to have a quick look into a script – not for development. πŸ˜‰

    • #219561
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      in addition to the above script, and I can’t figure out how to add this I would like to add the following

      total nr of groups a user is member of
      total nr of groups the user is removed from
      total nr of groups we where not able to remove the user from

      thanks for any pointers in this direction

    • #219657
      Participant
      Topics: 12
      Replies: 1610
      Points: 2,508
      Helping Hand
      Rank: Community Hero

      Logs have their place, but you’re taking all of the analysis functionality of Powershell if you are not using objects. If you do something like this:

      Connect-AzureAD
      $users = import-csv c:\temp\toRemove.csv
      
      $results = foreach ($user in $users) {
          $UserObjectID = get-AzureAdUser -objectId $user.SamAccountName | Select-Object -Property objectID
          $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $($userObjectID.objectID)
          
          if ($UserObjectID) {
              foreach ($group in $UserObjectIDGroupMemberShip) {
                  try {
                      Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $SelectUserObjectID
                      [PSCustomObject]@{
                          User = $user.SamAccountName
                          Group = $group.Name
                          Status = 'Success'
                      }
                  }
                  catch {
                      [PSCustomObject]@{
                          User = $user.SamAccountName
                          Group = $group.Name
                          Status = 'Failed - {0}' -f $_
                      }
                  }
              }
          }
          else {
              [PSCustomObject]@{
                  User = $user.SamAccountName
                  Group = $NULL
                  Status = 'Failed - User not found.'
              }       
          }
      }
      
      $results
      

      After you have the results, you can do analysis paralysis with Where-Object and Group-Object

      #Mock data
      $results = @()
      $results += [PSCustomObject]@{
          User = 'User123'
          Group = 'Group123'
          Status = 'Success'
      }
      $results += [PSCustomObject]@{
          User = 'User123'
          Group = 'Group124'
          Status = 'Failed - Permission Denied'
      }
      $results += [PSCustomObject]@{
          User = 'User125'
          Group = $null
          Status = 'Failed - User Not Found.'
      }
      
      #Count by status
      $results | Group-Object -Property Status
      
      #Investigate failures
      $results | Where{$_.Status -ne 'Success'}
      
      #All failures grouped by user
      $results | Where{$_.Status -ne 'Success'} | Group-Object -Property User
      

      Output:

      Count Name                      Group
      ----- ----                      -----
          1 Failed - Permission Deni… {@{User=User123; Group=Group124; Status=Failed - Permission Denied}}
          1 Failed - User Not Found.  {@{User=User125; Group=; Status=Failed - User Not Found.}}
          1 Success                   {@{User=User123; Group=Group123; Status=Success}}
      
      User   : User123
      Group  : Group124
      Status : Failed - Permission Denied
      
      
      User   : User125
      Group  :
      Status : Failed - User Not Found.
      
          1 User123                   {@{User=User123; Group=Group124; Status=Failed - Permission Denied}}
          1 User125                   {@{User=User125; Group=; Status=Failed - User Not Found.}}
      
    • #219864
      Participant
      Topics: 28
      Replies: 67
      Points: 375
      Rank: Contributor

      @Rob thanks for your help however when I run your version there is nothing that is removed I get these errors

      
      User Group Status
      —- —– ——
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      user1 Failed – Error occurred while executing RemoveGroupMember …
      {@{User=User123; Group=Group123; Status=Success}}
      {@{User=User123; Group=Group124; Status=Failed – Permission Denied}}
      {@{User=User125; Group=; Status=Failed – User Not Found.}}
      User123 Group124 Failed – Permission Denied
      User125 Failed – User Not Found.
      {@{User=User123; Group=Group124; Status=Failed – Permission Denied}}
      {@{User=User125; Group=; Status=Failed – User Not Found.}}
      

      when I run my version the groups do get removed correctly can it be that this has something to do with the PScustomobject?

       

       

    • #219975
      Participant
      Topics: 12
      Replies: 1610
      Points: 2,508
      Helping Hand
      Rank: Community Hero

      It was a suggestion, not tested code. When you do a direct lookup on an Id, it either returns the object or fails, so it needs to be wrapped in a try\catch with the -ErrorAction set to stop. Tested the following:

      $creds = Get-Credential -UserName 'rob.simmers@mycompany.com' -Message 'Enter your credentials'
      
      Connect-AzureAD -Credential $creds
      
      #Emulate CSV
      $users = @()
      $users += [pscustomobject]@{SamAccountName = 'rob.simmers@mycompany.com'}
      $users += [pscustomobject]@{SamAccountName = 'dont.exist@mycompany.com'}
      $users += [pscustomobject]@{SamAccountName = 'john.smith@mycompany.com'}
      
      #$users = import-csv c:\temp\toRemove.csv
      
      $results = foreach ($user in ($users | Select -ExpandProperty SamAccountName)) {
          try {
              $UserObjectID = get-AzureAdUser -objectId $user | Select-Object -Property objectID -ErrorAction Stop
              $UserObjectIDGroupMemberShip = get-AzureAdUserMembership -objectID $($userObjectID.objectID)
          
              foreach ($group in $UserObjectIDGroupMemberShip) {
                  try {
                      Remove-AzureADGroupMember -ObjectId $group.objectID -MemberId $UserObjectID -ErrorAction Stop
                      [PSCustomObject]@{
                          User   = $user
                          Group  = $group.DisplayName
                          Status = 'Success'
                      }
                  }
                  catch {
                      [PSCustomObject]@{
                          User   = $user
                          Group  = $group.DisplayName
                          Status = 'Failed - Group Removal. {0}' -f $_
                      }
                  }
              }
          }
          catch {
              [PSCustomObject]@{
                  User   = $user
                  Group  = $NULL
                  Status = 'Failed - User lookup. {0}' -f $_
              }
      
          }          
      }
      
      $results
      

      Output:

      User                       Group                                   Status                                                                                                                                                                
      ----                       -----                                   ------                                                                                                                                                                
      rob.simmers@mycompany.com Everyone                                Success                                                                                                                                                               
      rob.simmers@mycompany.com All Company                             Success                                                                                                                                                               
      rob.simmers@mycompany.com Strategic Vision Team                   Success                                                                                                                                                               
      rob.simmers@mycompany.com Information Technology                  Success                                                                                                                                                               
      dont.exist@mycompany.com                                          Failed - User lookup. Error occurred while executing GetUser ...                                                                                                      
      john.smith@mycompany.com  Everyone                                Success                                                                                                                                                               
      john.smith@mycompany.com  All Company                             Success                                                                                                                                                               
      john.smith@mycompany.com  Marketing & Sales                       Success                                                                                                                                                               
      john.smith@mycompany.com  Information Technology                  Success 
      
      • This reply was modified 1 month, 1 week ago by Rob Simmers. Reason: Un-Remark Remove-AzureADGroupMember - Note this command doesn't appear to have a -Whatif switch
Viewing 19 reply threads
  • You must be logged in to reply to this topic.