PowerShell Genie

PowerShell Entra users and groups

Managing Entra ID users and groups through Graph works, with a few sharp edges worth knowing before you write a script that changes things.

Lesson 2 min read Windows PowerShell 5.1 and PowerShell 7

Documentation: Microsoft Learn

Overview

Synchronised objects cannot be edited in the cloud. A user with OnPremisesSyncEnabled set to true is mastered in on-premises AD, and Update-MgUser on their attributes either fails or is overwritten at the next sync cycle. Check that property before writing anything, and make the change in AD instead.

Group membership depends on the group type. A dynamic group's membership comes from a rule, so Add-MgGroupMember on it is refused. Assigned groups accept explicit members. Mail-enabled security groups are managed through Exchange Online rather than Graph. So the right cmdlet depends on the group, which is why inspecting groupTypes first matters.

Graph filter syntax is OData, not PowerShell and not AD. It uses eq rather than -eq, and constructs like groupTypes/any(...) for collections. Some filters need -ConsistencyLevel eventual together with -CountVariable, which the error message will tell you.

Deleted users go to a recycle bin for 30 days and are restorable, which is a useful thing to know before you panic about a bulk operation.

Licence assignment moved: Set-MgUserLicense is the current cmdlet, and group-based licensing is the better approach at scale.

Inspect this example’s structure

Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.

[pscustomobject]@{ Users = 'Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled' Groups = 'Get-MgGroup -Filter "groupTypes/any(c:c eq ''DynamicMembership'')"' Members = 'Get-MgGroupMember -GroupId <id> -All' Licences = 'Get-MgUserLicenseDetail -UserId <upn>' } | Format-List
  1. Stage 1[pscustomobject]@{Positional values or no named parameters
  2. Stage 2Format-ListPositional values or no named parameters

    An example to inspect

    Preview the example. Sign in for the full lesson and activities.

    [pscustomobject]@{
      Users = 'Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled'
      Groups = 'Get-MgGroup -Filter "groupTypes/any(c:c eq ''DynamicMembership'')"'
      Members = 'Get-MgGroupMember -GroupId <id> -All'
      Licences = 'Get-MgUserLicenseDetail -UserId <upn>'
    } | Format-List

    What happens

    This prints four queries. The first includes OnPremisesSyncEnabled deliberately, because that single property tells you whether the object is yours to edit. The second uses OData collection syntax to find dynamic groups, which are the ones that will reject a membership change.

    Worth remembering

    • OnPremisesSyncEnabled means the object is mastered in on-premises AD.
    • Dynamic groups reject explicit membership changes.
    • Graph filters are OData: eq, not -eq.
    • Deleted users are restorable for 30 days.

    Primary documentation

    PowerShell objects and pipelines documentation

    Try it

    Expected output · prints command text; does not execute these commands

    1[pscustomobject]@{
    2 Users = 'Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled'
    3 Groups = 'Get-MgGroup -Filter "groupTypes/any(c:c eq ''DynamicMembership'')"'
    4 Members = 'Get-MgGroupMember -GroupId <id> -All'
    5 Licences = 'Get-MgUserLicenseDetail -UserId <upn>'
    6} | Format-List

    Example reader

    Inspect this page's example

    Fictional browser data when supported

    Run supported commands against the practice data, or inspect the example without executing it.

    Ready to inspect.

      Prints Entra queries, including the sync-status check that gates edits.

      Show reference output

      Expected output · prints command text; does not execute these commands

      Users    : Get-MgUser -All -Property DisplayName,UserPrincipalName,AccountEnabled,OnPremisesSyncEnabled
      Groups   : Get-MgGroup -Filter "groupTypes/any(c:c eq 'DynamicMembership')"
      Members  : Get-MgGroupMember -GroupId <id> -All
      Licences : Get-MgUserLicenseDetail -UserId <upn>

      Practise this

      Find disabled cloud accounts

      Connect to the fictional tenant first. Request AccountEnabled and return DisplayName, UserPrincipalName and AccountEnabled for disabled users.

      Review the lesson

      Keep going

      Next: Exchange Online PowerShell

      Check your understanding

      A user query omits a property you need. Does that prove the directory value is empty?

      Genie guidePowerShell Entra users and groups

      Managing Entra ID users and groups through Graph works, with a few sharp edges worth knowing before you write a script that changes things.