After many twists and turns since August 2021, the MSOnline module retirement will happen in April 2025. The AzureAD module will then retire in the 3rd quarter. It’s way past time to upgrade PowerShell scripts. The question is whether to use the Entra module or the Microsoft Graph PowerShell SDK. I know which option is best and say why in this article.
Microsoft released the SharePoint Pages API in mid-2024. This article describes how to create and publish a news item using cmdlets from the Microsoft Graph PowerShell SDK based on the API. The net result is that the API appears to work well but some problems are evident in the cmdlets. Or maybe it’s just my lack of knowledge!
The Office365ITPros GitHub repository holds over 300 PowerShell scripts showing how to interact with Microsoft 365 and Entra ID. Anyone can contribute to Office365ITPros by forking the code to a copy of the repository and making changes to scripts there. If you want, you can push the changes back to us so that we can consider their inclusion in Office365ITPros. It’s a great example of community in action.
Two types of retention labels are in use: Microsoft 365 retention labels and MRM retention tags. Clients hide the difference, but the Microsoft Graph PowerShell SDK cmdlets can only process Microsoft 365 retention labels for files stored in SharePoint Online and OneDrive for Business. EWS can manage MRM retention tags, but it’s on a fast path to retirement in 2026…
This article describes how to report the audit events for a user over a single day. The task seems simple, but inconsistency in audit payloads makes it harder. Workloads don’t help by the variations in audit events. In any case, persistence and knowledge about what the audit event captured for an action helps to decode the data, as illustrated by the script detailed here.
Service principal sign-in activity is a new insight available in the Entra admin center. As explained here, it’s also possible to use PowerShell to fetch and analyze the data to derive new insights into what apps create service principals in a tenant and what organizations own the apps. Some detective work is needed to fully understand the data. That might be an ongoing task, but at least we have the data.
The unified audit log is full of interesting information about who did what and when they did it. In this article, I describe how to use file operations audit events to find the last accessed date for documents in a SharePoint Online site. It’s data that isn’t available in the Microsoft Graph, but it is in the unified audit log.
This article describes how to create eligible and active PIM role assignment requests using cmdlets from the Microsoft Graph PowerShell SDK. Although the PowerShell code is straightforward, Microsoft recommends using the Entra admin center for Privileged Identity Management. But you can automate the management of role assignment requests if you want to.
Group-based licensing is a mechanism to make it easier to assign and manage product licenses for large sets of user accounts. In this article, we discuss how to use Microsoft Graph PowerShell SDK cmdlets to manage group-based license assignments in a Microsoft 365 tenant. Assigning licenses to groups is very much like direct assignments, but some differences exist.
Many articles describe how to disable a service plan for a product license assigned to a Microsoft 365 account, but few cover how to enable service plans should the need arise afterward. This article covers the basics of disabling and enabling service plans for Microsoft 365 licenses using PowerShell, including the very important step of finding existing disabled plans. Everything’s easy once you know how.
The question of how best to write PowerShell for Microsoft 365 was asked during a TEC 2024 PowerShell workshop. There are many variables, and one has the right answer. To start the ball rolling, this article describes how I write PowerShell for Microsoft 365 using a variety of modules such as Exchange, SharePoint, Teams, and the Microsoft Graph PowerShell SDK.
Unsurprisingly, Microsoft announced the deprecation of the Revoke-SPOUserSession cmdlet for November 2024. The cmdlet is replaced by the Revoke-MgUserSignInSession cmdlet, which works across Microsoft 365 rather than just SharePoint Online. All of this happened while the 2nd annual PowerShell Script-Off happened at TEC 2024 and competitors struggled with what to do to secure a user account for an ex-employee.
An article described some benefits that could be gained from not installing the complete Microsoft Graph PowerShell SDK. The question is whether the claimed benefits are more theoretical than actual. It’s hard to say because it all depends on how someone uses the SDK for development or to run scripts. Anyway, it’s a topic worth discussing.
A recent script demonstrated how to import contacts into user mailboxes using a list in a SharePoint site as the source. With a quick change, a CSV file becomes the source. This is a great example of how adaptable PowerShell is and how to update code found in articles to meet your needs. If you do ask an author to change their code, remember to try to make the change yourself first, and if you fail, explain to the author why the change should be made.
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.
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.
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 task to find manager for Entra ID accounts seems simple until you find the bunch of utility accounts created by Exchange Online that should be ignored. This makes the task more “interesting” when the time comes to find user accounts that don’t have assigned managers. Eventually, all the filters work, and you have a result, but the task is more complicated than it should be.
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.
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…
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.
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.
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.
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).
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.
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.
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.
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?
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.
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!
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.
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.
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).
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!
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.
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
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.
A new convert to internal user preview feature allows Entra ID administrators to convert external accounts to internal accounts. An option is available in the Users section of the Entra admin center or PowerShell can be used to automate the conversion of accounts. It’s a useful feature that should prove popular.
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.
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.