Transferring Reusable PowerShell Objects Between Microsoft 365 Tenants

People often need to transfer objects or code between Microsoft 365 tenants. When it comes to dealing with objects, the Microsoft Graph PowerShell SDK’s ToJsonString method is very useful. The method outputs a string containing JSON content, but only for object properties that have a value. This makes the much easier to use the output as the basis for a template object or as the payload body to create an object in another tenant.

PnP PowerShell Changes Its Entra ID App

On August 21, 2024, news emerged that the PnP PowerShell module will transition from using a multi-tenant Entra ID app to a tenant-specific app. The change is scheduled for September 9, 2024, which doesn’t leave a lot of time available for developers to review, update, and test PowerShell scripts based on PnP PowerShell. Some extra warning would have been nice.

Handling the Too Many Retries Error and Dealing with Odd Numbers of Audit Events

The AuditLog Query Graph API remains in beta status but cmdlets are now available in the Microsoft Graph PowerShell SDK. This led to some oddities in results when the number of audit events found by a search didn’t match those reported by the Purview compliance portal. It all worked out in the end. In other news, the Set-MgRequestContext helped sort out some retry problems.

The Maddening Side of the Microsoft Graph PowerShell SDK

All software has unique quirks, and the foibles of the Microsoft Graph PowerShell SDK are well known. But it’s much harder when the underlying foundation contributes to the craziness as described in this article. Graph pagination works in a specific way and Microsoft tunes the Graph to deliver great performance by reducing the set of properties returned for objects. Both can cause concern for developers.

Adding Cost Center Reporting to the Microsoft 365 Licensing Report

Microsoft 365 LIcensing Report

The Microsoft 365 licensing report now supports a cost center analysis based on cost center values stored in an Exchange custom attribute. The new analysis is entirely optional, but it seems like many tenants store cost center values in custom attributes, so this update might work well for them. That is, if the cost center data stored in Exchange is accurate… Rubbish in always means rubbish out…

Upgrading the Teams and Groups Activity Report to 6.0

The Teams and Groups activity report is a popular script that helps administrators identify inactive teams and groups within a Microsoft 365 tenant. The script code has been developed over the years. The last version converted to Graph API requests to improve performance. This time, the upgrade is to use the Microsoft Graph PowerShell SDK to make the code easier to maintain.

The Right Way to Replace the Remove-SPOExternalUser Cmdlet

Microsoft says they will remove the Remove-SPOExternalUser cmdlet starting July 29. They recommend using Remove-AzureADUser as a replacement. It’s a bad call because that cmdlet is part of a now-retired and soon to be deprecated module. Overall, recommendations like this make you think that Microsoft doesn’t know what’s happening across the whole of Microsoft 365. And you might be right.

Adding Details of Authentication Methods to the Tenant Passwords and MFA Report

V1.2 of the User Passwords and MFA report includes the names of authentication methods registered for user accounts. V1.3 expands the amount of detail reported for each method, such as the phone number used for SMS challenges, or the email address used for SSPR. It’s a small but important detail that’s useful to administrators. However, it also comes with a potential privacy issue, so the script must handle that too.

Planner User Policy Stops Task and Plan Deletions

The Set-PlannerUserPolicy cmdlet allows Microsoft 365 tenant administrators stop users deleting tasks created by other users. However, an undocumented consequence of setting the policy for user accounts is that it stops those accounts removing plans too. The unexpected block imposed by Set-PlannerUserPolicy caused me problems when attempting to delete a plan with PowerShell. It would be nice if the modules created by Microsoft worked as expected (and as documented).

Version 1.9 of the Microsoft 365 Licensing Report

The Microsoft 365 Licensing Report is a popular PowerShell script that’s just been updated to V1.9 with a bunch of changes to highlight different aspects such as license costs for disabled user accounts and inactive user accounts. Copious use of some very dubious color choices makes the HTML report created by the script look very nice (if you’re color blind) and the new version can generate an Excel worksheet.

Working with Calendar Permissions using the Microsoft Graph PowerShell SDK

The Set-MailboxFolderPermission cmdlet is usually used to set calendar permissions, including the permission for the default user to allow everyone in an organization to see each other’s calendars. But you can use cmdlets from the Microsoft Graph PowerShell SDK too. The Graph SDK cmdlets are faster, but not enough to warrant replacing the Exchange cmdlet in scripts. We explain why here.

To Splat or Not to Splat, That’s the Question

Splatting is an optional PowerShell technique designed to make it easier to pass parameter values for cmdlets. It’s a personal choice whether to use splatting instead of passing values to individual parameters in the command line. Although the Microsoft Graph PowerShell SDK can be a little strange at times, you can use splatting with SDK cmdlets, even with some pretty complex parameters such as those used to filter objects.

Interpreting Audit Records for Teams Meeting Recordings (Again)

Three years ago, I wrote a script to analyze the audit records generated for Teams meeting recordings. Then things changed in terms of how the audit records were generated and how the Search-UnifiedAuditLog cmdlet returns audit search results. All of which meant that considerable work was needed to revamp (rewrite) the script. Maybe you need to check any script that uses the Search-UnifiedAuditLog cmdlet too?

Report Delegated Permission Assignments for Users and Apps

This article describes how to use the Microsoft Graph PowerShell SDK to report delegated permission assignments to user accounts and apps. Like in other parts of Microsoft 365, the tendency exists to accrue delegated permissions for both user accounts and apps over time. There’s nothing wrong with having delegated permissions in place, if they are appropriate and needed – and that’s why we report their existence.

Choosing Between Graph API Requests or Graph SDK Cmdlets

Deciding whether to use Microsoft Graph PowerShell SDK cmdlets or Graph API requests is sometimes not easy. Some say that it’s best to use Graph API requests everywhere and avoid the complication of possibly buggy Graph PowerShell SDK cmdlets. My approach is different. I start with Graph PowerShell SDK cmdlets and only resort to Graph API requests when absolutely necessary. It works for me!

Reporting Mailbox Audit Configurations

A request came in for a PowerShell script to report mailbox audit configurations to check that the important new events are being generated by mailboxes. After diverting into the hellhole of Microsoft licensing, normal sanity was resumed and a PowerShell script written to do the job. The script generates a CSV file or Excel worksheet for tenant administrators to review. After that, it’s up to you.

More Microsoft Graph PowerShell SDK Problems

Some problems emerged in V2.17 and V2.18 of the Microsoft Graph PowerShell SDK. In one case, Microsoft changed cmdlet names. In another, it’s an identity issue caused by incompatible assemblies. In both cases, questions have to be asked about the level of testing done by Microsoft before they release a new module. Bugs do happen, but testing should catch the obvious problems.

Sending Urgent Teams Chats with PowerShell

A reader asked if it is possible to script sending chat messages. In this article, we explore how to compose and send Teams urgent messages to a set of recipients using Microsoft Graph PowerShell SDK cmdlets. The conversation with each recipient is a one-to-one chat that Teams either creates from scratch or reuses (if a suitable one-on-one chat exists).

How to Remove a Single Service Plan from User Accounts with PowerShell

Some years ago, I wrote a script to demonstrate how to remove service plans with PowerShell. This article describes some upgrades to make the script even better by improving the code and leveraging complex Microsoft Graph queries against the license information stored for Entra ID user accounts. It’s PowerShell, so feel free to change the script!

Modifying the Teams Tenant Federation Configuration with PowerShell

A new parameter for the Set-CsTenantFederationConfiguration cmdlet made me look at the Teams tenant federation configuration again to improve how a script works. Instead of taking all the domains guest accounts came from and adding them to the configuration, I created a function to check if the tenant uses Microsoft 365. If it does, we add the tenant to the allow list in the tenant federation configuration. If not, we ignore the domain.

How to Retrieve Loop Workspaces Data with PowerShell

A previous attempt to write a script to report all Loop workspaces in a tenant was flawed because it only retrieved the first 200 workspaces. I hadn’t realized that the Get-SPOContainer cmdlet supported an odd form of pagination to retrieve workspace data. In any case, I figured out how to page top find all available workspaces and updated the script. It’s just another example of oddness in the SharePoint Online PowerShell module

Graph and PowerShell Hiccups for the Groups and Teams Report Script

The Microsoft 365 Groups and Teams Activity Report is a PowerShell script that I’ve worked on since 2016 (not all the time). Some recent Graph hiccups meant that I had to apply some fixes and workarounds. At the same time, some users hit the infamous ‘not recognized as a valid datetime’ problem, so another update was needed. All good, clean fun.

Does Microsoft Care about SharePoint Online PowerShell?

Microsoft’s support for SharePoint Online PowerShell has degraded over the last few years. Pnp.PowerShell is now the best option as not much is happening in the official SharePoint Online management module or the tenant settings Graph API. the lack of progress is a pity, but perhaps it’s also true that community-driven projects sometimes deliver better results.

Despite the Doubters, Microsoft 365 Administrators Should Continue Using PowerShell

A recent article by a Microsoft MVP attempted to lay out a case that tenants should not use Microsoft 365 PowerShell and use ISV products instead. It’s a silly position to argue. PowerShell is an important automation tool for administrators that can’t be replaced by any ISV product. ISV products have their place and fill many gaps, but arguing to dump PowerShell and use ISV products instead just can’t be justified.

Report OneDrive for Business Storage Based on Usage Data

If you wanted to write a PowerShell script to create a OneDrive storage report, you’d probably use the cmdlets from the SharePoint Online management module. But accessing OneDrive usage data via the Graph is much faster. And you can include information from other sources, such as user properties, to build out the report. All explained here.

Why You Should Not Upgrade to Microsoft Graph PowerShell SDK V2.14

Usually, we recommend that Microsoft 365 tenants use the latest version of the Microsoft Graph PowerShell SDK. However, a serious bug in V2.14 means that this (and perhaps V2.13.1) should be avoided until Microsoft fixes a problem that causes spurious output to be included when cmdlets like Get-MgUser and Get-MgGroup are run.

Tracking Licensing Costs for Microsoft 365 Tenants

The latest version of the Microsoft 365 Licensing Report script includes code to generate cost analyses for the departments and countries assigned to user accounts. Everything works well if the properties of Entra ID user accounts are complete and accurate. Sometimes this isn’t so, and that leads to problems when attributing costs at a department or country level.

How Many Message Center Announcements End Up Being Delayed?

This article describes how to use the Microsoft Graph PowerShell SDK to retrieve and interpret Microsoft 365 message center posts with the intention of discovering what percentage of announcemengts end up being delayed (not being available at the predicted date). Teams makes lots of feature announcements and over 57% of those announcements are delayed.

Use the Graph SDK to Access Microsoft 365 Service Health Information

The Microsoft Graph includes the Service Communications API. SDK cmdlets can use the API to retrieve and work with service health data. In this article, we show how to use Graph SDK cmdlets (based on the API) to fetch and work with service health data, including creating an email report to update people about the current state of tenant health.

New MSIdentityTools Cmdlet to Report OAuth Permissions

The latest version of the MSIndentityTools PowerShell module includes the Export-MsIdAppConsentGrantReport cmdlet to generate a report of OAuth app permissions. Allied with the ImportExcel module, the cmdlet can produce a very nice workbook containing lots of information about permissions held by the apps in a tenant. But even better, you can export the data to PowerShell and use it in your scripts.

Microsoft Deprecates Old Exchange Audit Search Cmdlets

A January 26 post announces the deprecation of four old Exchange audit cmdlets in favor of the Search-UnifiedAuditLog cmdlet. Removing old cmdlets is fine, but it would be nice if Microsoft took the opportunity to make Search-UnifiedAuditLog work better. Too many inconsistencies exist in how workloads provide information in audit events and Microsoft has made some recent unannounced changes.

Mastering Microsoft Graph PowerShell SDK Foibles

Entra ID supports user extension attributes but the same facility is unavailable for group objects. That seems strange, but it might be due to the way that Entra ID thinks about group object. In any case, it’s an inconsistency that Microsoft should address. Also covered is how to report problems with Graph SDK cmdlets and a new function to help you understand the permissions needed to run a script.

Reporting Entra ID Admin Consent Requests

A question came in about how to report admin consent requests as viewed through the Entra ID admin center. PowerShell does the trick, once you know how. The key thing is to find the right cmdlet to use. Once you know that, the rest is pretty easy as we explain in this article.

Entra ID Improves Registered App Security

The preview app instance property lock feature designed to improve the security of Entra ID registered apps is becoming the default for new apps. In this article, we describe how to update the app instance property lock to reflect the new default setting using cmdlets from the Microsoft Graph PowerShell SDK, including a script you can download and run.

Reporting User and Group Assignments for Enterprise Applications

A reader asked how to report user and group assignments for enterprise apps. As it turns out, this isn’t particularly difficult, if you know where to look. Our script uses the Graph SDK to check service principals, filters out the apps to check, and extracts the user and group assignments before reporting what it finds.