Problems – Office 365 for IT Pros https://office365itpros.com Mastering Office 365 and Microsoft 365 Tue, 21 May 2024 23:38:37 +0000 en-US hourly 1 https://i0.wp.com/office365itpros.com/wp-content/uploads/2024/06/cropped-Office-365-for-IT-Pros-2025-Edition-500-px.jpg?fit=32%2C32&ssl=1 Problems – Office 365 for IT Pros https://office365itpros.com 32 32 150103932 More Microsoft Graph PowerShell SDK Problems https://office365itpros.com/2024/05/06/microsoft-graph-powershell-sdk-217/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-graph-powershell-sdk-217 https://office365itpros.com/2024/05/06/microsoft-graph-powershell-sdk-217/#comments Mon, 06 May 2024 04:00:00 +0000 https://office365itpros.com/?p=64674

Odd Replacement Cmdlets appear in Microsoft Graph PowerShell SDK V2.17 and Azure Automation Issues in V2.18

Updated 15 May 2024

Microsoft Graph PowerShell SDK V2.18

Last week was odd for me. I headed to Orlando for the M365 Community Conference on Sunday and arrived at the Dolphin hotel feeling somewhat odd. A few hours later, I was flat on my back unable to move with a combination of a horrible cough and the effects of a norovirus. Enough to say that it wasn’t pretty.

The conference swung into full action on Tuesday, and I spoke (between coughs) about the Microsoft Graph PowerShell SDK. I think it’s fair to say that I have a love-hate relationship with the software. I like the access to all sorts of Microsoft 365 data enabled through the SDK cmdlets, but I dislike some of its foibles.

I also hate when Microsoft makes changes that seem to be firmly in the category of shooting itself in the foot, like the spurious output generated for cmdlets introduced in V2.13.1 and worsened in V2.14. Stuff like this shouldn’t get through basic testing.

Update: Microsoft has released V2.19 of the SDK to fix the reported problems. They describe the affected cmdlets in a May 15 blog.

The Case of the DirectoryObjectByRefs Cmdlets

Which brings me to a problem that seems to have surfaced in V2.17. Until this time, the Remove-MgGroupMemberByRef cmdlet worked to remove a member from a group by passing the user account identifier for the member and the group identifier. With V2.17, the following happens:

Remove-MgGroupMemberByRef -DirectoryObjectId $UserId -GroupId $GroupId
Remove-MgGroupMemberByRef: A parameter cannot be found that matches parameter name 'DirectoryObjectId'

The same happens with the Remove-MgGroupOwnerByRef cmdlet to remove a group member (but not if the action would leave the group ownerless).

Microsoft’s response is documented here and it is a calamity. Not only does it appear that other cmdlets are involved (like Remove-MgApplicationOwnerByRef – I have asked Microsoft for a definitive list), but the fix is terrible. No experienced PowerShell person would think that it is a good idea to fix a problem in a cmdlet by introducing a brand-new cmdlet, but that’s what Microsoft did by including cmdlets like Remove-MgGroupMemberDirectoryObjectByRef and Remove-MgGroupOwnerDirectoryObjectByRef in V2.17.

The SDK developers might be pleased that V2.17 contains functional cmdlets to remove group members and owners, but anyone who wrote scripts prior to V2.17 based on the old cmdlets is left high and dry.

I hadn’t noticed the problem because I haven’t run the affected cmdlets for a while. But Ryan Mitchell of Northwestern University had, and he brought the matter to my attention after the session at the Microsoft 365 Community Conference. Suffice to say that the necessary protests have been made in the right quarters. I had the opportunity in Orlando to chat with some senior members of the Graph development team who acknowledged that this is not the way that cmdlet problems should be addressed and that overall Graph SDK quality must be improved. Specifically for the group cmdlets, Microsoft is investigating how the situation developed. It could be that this is a side effect of the famous AutoRest process that generates SDK cmdlets from Graph APIs. We’ll see in time.

Update May 9: Microsoft has published V2.19 of the SDK to address the problem with cmdlet renaming. They’ve introduced aliases to make sure that scripts continue to work with the old cmdlets.

Microsoft Graph PowerShell SDK V2.18 and Azure Automation

Microsoft released V2.18 of the Microsoft Graph PowerShell SDK last week. After installing the new module and running some tests, everything checked out and I duly tweeted that the new module was available.

But problems lurked for Azure Automation runbooks configured for PowerShell 5.1 because people noted that they couldn’t use the Groups module after connecting with a user-provided access token obtained using the Get-AzAccessToken cmdlet. Everything works with PowerShell 7, but not with the earlier release. It seems like a clash occurs between the version of the Azure identity assembly loaded by the AzAccounts module. In any case, Microsoft is investigating (here are the full details) and the advice is to stay with V2.17 if you use Azure Automation until Azure updates their assembly.

Time for a Checkup

It’s disappointing to see issues like these continue to appear in new versions of the Microsoft Graph PowerShell SDK. Basic testing and some knowledge about how people use PowerShell in practice should have caught these issues. Their existence lessens faith in the SDK. After all, who wants to chase new bugs in a module that’s refreshed monthly?

Chapter 23 of the Office 365 for IT Pros eBook referenced examples of the cmdlets affected by the V2.17 issue. We’ve issued update 107.1 with amended text. The nature of an eBook means that it’s much easier to address problems in text than with printed books and we do try and fix known issues as quickly as we can. For everyone else who uses the Microsoft Graph PowerShell SDK for group management or Azure Automation, it’s time to check that everything’s working as expected.


So much change, all the time. It’s a challenge to stay abreast of all the updates Microsoft makes across the Microsoft 365 ecosystem. Subscribe to the Office 365 for IT Pros eBook to receive monthly insights into what happens, why it happens, and what new features and capabilities mean for your tenant.

]]>
https://office365itpros.com/2024/05/06/microsoft-graph-powershell-sdk-217/feed/ 4 64674
Mastering the Foibles of the Microsoft Graph PowerShell SDK https://office365itpros.com/2023/02/13/microsoft-graph-powershell-sdk-prob/?utm_source=rss&utm_medium=rss&utm_campaign=microsoft-graph-powershell-sdk-prob https://office365itpros.com/2023/02/13/microsoft-graph-powershell-sdk-prob/#comments Mon, 13 Feb 2023 01:00:00 +0000 https://office365itpros.com/?p=59070
He looks happy, but he hasn't hit some of the Microsoft Graph PowerShell SDK foibles yet...
He looks happy, but he hasn’t hit some of the SDK foibles yet…

Translating Graph API Requests to PowerShell Cmdlets Sometimes Doesn’t Go So Well

The longer you work with a technology, the more you come to know about its strengths and weaknesses. I’ve been working with the Microsoft Graph PowerShell SDK for about two years now. I like the way that the SDK makes Graph APIs more accessible to people accustomed to developing PowerShell scripts, but I hate some of the SDK’s foibles.

This article describes the Microsoft Graph PowerShell SDK idiosyncrasies that cause me most heartburn. All are things to look out for when converting scripts from the Azure AD and MSOL modules before their deprecation (speaking of which, here’s an interesting tool that might help with this work).

No Respect for $Null

Sometimes you just don’t want to write something into a property and that’s what PowerShell’s $Null variable is for. But the Microsoft Graph PowerShell SDK cmdlets don’t like it when you use $Null. For example, let’s assume you want to create a new Azure AD user account. This code creates a hash table with the properties of the new account and then runs the New-MgUser cmdlet.

$NewUserProperties = @{
    GivenName = $FirstName
    Surname = $LastName
    DisplayName = $DisplayName
    JobTitle = $JobTitle
    Department = $Null
    MailNickname = $NickName
    Mail = $PrimarySmtpAddress
    UserPrincipalName = $UPN
    Country = $Country
    PasswordProfile = $NewPasswordProfile
    AccountEnabled = $true }
$NewGuestAccount = New-MgUser @NewUserProperties

New-MgUser fails because of an invalid value for the department property, even though $Null is a valid PowerShell value.

New-MgUser : Invalid value specified for property 'department' of resource 'User'.
At line:1 char:2
+  $NewGuestAccount = New-MgUser @NewUserProperties
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: ({ body = Micros...oftGraphUser1 }:<>f__AnonymousType64`1) [New-MgUser
   _CreateExpanded], RestException`1
    + FullyQualifiedErrorId : Request_BadRequest,Microsoft.Graph.PowerShell.Cmdlets.NewMgUser_CreateExpanded

One solution is to use a variable that holds a single space. Another is to pass $Null by running the equivalent Graph request using the Invoke-MgGraphRequest cmdlet. Neither are good answers to what should not happen (and we haven’t even mentioned the inability to filter on null values).

Ignoring the Pipeline

The pipeline is a fundamental building block of PowerShell. It allows objects retrieve by a cmdlet to pass to another cmdlet for processing. But despite the usefulness of the pipeline, the SDK cmdlets don’t support it and the pipeline stops stone dead whenever an SDK cmdlet is asked to process incoming objects. For example:

Get-MgUser -Filter "userType eq 'Guest'" -All | Update-MgUser -Department "Guest Accounts"
Update-MgUser : The pipeline has been stopped

Why does this happen? The cmdlet that receives objects must be able to distinguish between the different objects before it can work on them. In this instance, Get-MgUser delivers a set of guest accounts, but the Update-MgUser cmdlet does not know how to process each object because it identifies an object is through the UserId parameter whereas the inbound objects offer an identity in the Id property.

The workaround is to store the set of objects in an array and then process the objects with a ForEach loop.

Property Casing and Fetching Data

I’ve used DisplayName to refer to the display name of objects since I started to use PowerShell with Exchange Server 2007. I never had a problem with uppercasing the D and N in the property name until the Microsoft Graph PowerShell SDK came along only to find that sometimes SDK cmdlets insist on a specific form of casing for property names. Fail to comply, and you don’t get your data.

What’s irritating is that the restriction is inconsistent. For instance, both these commands work:

Get-MgGroup -Filter "DisplayName eq 'Ultra Fans'"
Get-MgGroup -Filter "displayName eq 'Ultra Fans'"

But let’s say that I want to find the group members with the Get-MgGroupMember cmdlet:

[array]$GroupMembers = Get-MgGroupMember -GroupId (Get-MgGroup -Filter "DisplayName eq 'Ultra Fans'" | Select-Object -ExpandProperty Id)

This works, but I end up with a set of identifiers pointing to individual group members. Then I remember from experience gained from building scripts to report group membership that Get-MgGroupMember (like other cmdlets dealing with membership like Get-MgAdministrationUnitMember) returns a property called AdditionalProperties holding extra information about members. So I try:

$GroupMembers.AdditionalProperties.DisplayName

Nope! But if I change the formatting to displayName, I get the member names:

$GroupMembers.AdditionalProperties.displayName
Tony Redmond
Kim Akers
James Ryan
Ben James
John C. Adams
Chris Bishop

Talk about frustrating confusion! It’s not just display names. Reference to any property in AdditionalProperties must use the same casing as used the output, like userPrincipalName and assignedLicenses.

Another example is when looking for sign-in logs. This command works because the format of the user principal name is the same way as stored in the sign-in log data:

[array]$Logs = Get-MgAuditLogSignIn -Filter "UserPrincipalName eq 'james.ryan@office365itpros.com'" -All

Uppercasing part of the user principal name causes the command to return zero hits:

[array]$Logs = Get-MgAuditLogSignIn -Filter "UserPrincipalName eq 'James.Ryan@office365itpros.com'" -All

Two SDK foibles are on show here. First, the way that cmdlets return sets of identifiers and stuff information into AdditionalProperties (something often overlooked by developers who don’t expect this to be the case). Second, the inconsistent insistence by cmdlets on exact matching for property casing.

I’m told that this is all due to the way Graph APIs work. My response is that it’s not beyond the ability of software engineering to hide complexities from end users by ironing out these kinds of issues.

GUIDs and User Principal Names

Object identification for Graph requests depends on globally unique identifiers (GUIDs). Everything has a GUID. Both Graph requests and SDK cmdlets use GUIDs to find information. But some SDK cmdlets can pass user principal names instead of GUIDs when looking for user accounts. For instance, this works:

Get-MgUser -UserId Tony.Redmond@office365itpros.com

Unless you want to include the latest sign-in activity date for the account.

Get-MgUser -UserId Tony.Redmond@office365itpros.com -Property signInActivity
Get-MgUser :
{"@odata.context":"http://reportingservice.activedirectory.windowsazure.com/$metadata#Edm.String","value":"Get By Key
only supports UserId and the key has to be a valid Guid"}

The reason is that the sign-in data comes from a different source which requires a GUID to lookup the sign-in activity for the account, so we must pass the object identifier for the account for the command to work:

Get-MgUser -UserId "eff4cd58-1bb8-4899-94de-795f656b4a18" -Property signInActivity

It’s safer to use GUIDs everywhere. Don’t depend on user principal names because a cmdlet might object – and user principal names can change.

No Fix for Problems in V2 of the Microsoft Graph PowerShell SDK

V2.0 of the Microsoft Graph PowerShell SDK is now in preview. The good news is that V2.0 delivers some nice advances. The bad news is that it does nothing to cure the weaknesses outlined here. I’ve expressed a strong opinion that Microsoft should fix the fundamental problems in the SDK before doing anything else.

I’m told that the root cause of many of the issues is the AutoRest process Microsoft uses to generate the Microsoft Graph PowerShell SDK cmdlets from Graph API metadata. It looks like we’re stuck between a rock and a hard place. We benefit enormously by having the SDK cmdlets but the process that makes the cmdlets available introduces its own issues. Let’s hope that Microsoft gets to fix (or replace) AutoRest and deliver an SDK that’s better aligned with PowerShell standards before our remaining hair falls out due to the frustration of dealing with unpredictable cmdlet behavior.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

]]>
https://office365itpros.com/2023/02/13/microsoft-graph-powershell-sdk-prob/feed/ 10 59070