Table of Contents
Upgrading the Microsoft 365 Groups Change Report Script
Don’t you just love it when people complain when a PowerShell script written ten years ago to accompany a blog post doesn’t work? This happened the other day for a Practical365.com article about a script to report information about new, changed, and deleted Office 365 Groups (now Microsoft 365 Groups). Apparently, the script didn’t complete and the expected email containing the information was never sent.
2016 is eons ago in Microsoft 365 time. So much has changed since, and it’s utterly unsurprising that code written then doesn’t work as well as it once did or fails altogether. My Teams and Groups Activity Report script dates from approximately the same time, and I know how many changes have been necessary to keep the code updated since.
Old Code Might Not Work Today
A quick glance at the code in the Microsoft 365 Groups Change Report script revealed some obvious issues, like the use of the Credential parameter when connecting to Exchange Online. Microsoft has deprecated the Credential parameter and will remove it in July 2026. Settings for the script are in an XML file on a local drive whereas today you might store the file in a SharePoint Online document library, and the email is sent using the old Send-MailMessage cmdlet using basic authentication with SMTP AUTH. All in all, the code is of its time and is a good example of why PowerShell scripts should be reviewed periodically.
In any case, it seems like the major functionality delivered by the script is to highlight the additions, removals, and updates of Microsoft 365 groups and the code accomplishes the goal by checking properties stored in a list (the XML file). If a group isn’t in the list, it’s a newly added group, and if a group is in the list and no longer available, it’s a deleted group.
The reason why this kind of mechanism is used is probably because the unified audit log didn’t exist when the script was written. Additions, deletions, and updates for Entra ID groups are captured in audit events and this removes the need to maintain a separate file to track group changes. Although the audit events include changes for security and mail-enabled security groups too, it’s easy to filter events relating to Microsoft 365 Groups from the full set.
Defining Steps for a Microsoft 365 Groups Change Report Script
A modern version of the Microsoft 365 Groups Change report script might include these steps:
- Connect to Exchange Online.
- Connect to Microsoft Graph.
- Find the set of Microsoft 365 Groups (using the Graph Get-MgGroup cmdlet is faster than the Exchange Get-UnifiedGroup cmdlet).
- Create a hash table containing group details to filter against when checking audit records.
- Search the audit log for group addition, deletion, and update events for the last 30 days.
- Populate a PowerShell list of events for Microsoft 365 Groups.
- Populate a PowerShell list of the Groups, including membership and ownership.
- Generate a HTML report file and either a CSV or XLSX file containing the group list, depending on the availability of the ImportExcel module.
- Send a mail message to a predetermined address (which could be a distribution list) with the HTML report as the message body (Figure 1) and the CSV or XLSX file as an attachment. The mailbox of the signed-in account is used to send the message.

One of the interesting things I found from the data reported by the script is that most of the updates for Microsoft 365 Groups came from system processes that use the Office 365 Exchange Online app or other background apps like the Group Configuration Processor or Microsoft Approval Management. The function of these apps is to make sure that the settings and membership of Microsoft 365 groups are accurate.
Download the Script
You can download my version of the Microsoft 365 Changes Report script from the Office 365 for IT Pros GitHub repository. Assuming that you can sign into a Microsoft Graph PowerShell SDK session with the right permissions, the code should run on any tenant, but you’ll have to update the code to change the recipient of the message.
This is a good example of a script that is well suited for Azure Automation. It would be easy to change the code to sign in with managed identities and have the script executed as a scheduled runbook every week, month, or whatever interval makes sense. Happy scripting!
You could also try to use https://learn.microsoft.com/en-us/graph/delta-query-groups?tabs=http to only track groups with changes this would make the script much faster.
The problem here is that using the delta feature requires a run to establish a baseline (Get-MgGroupDelta) followed by another run of Get-MgGroupDelta to find changes that occurred since the baseline was established. We don’t have that luxury because we don’t have a baseline from 30 days ago…
Actually, Get-MgGroupDelta doesn’t work because the SDK doesn’t expose the delta link (see https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/2062).
A delta can still be computed and used, but only with the basic Graph API, and only when you can create and use a baseline set.