IAMinerva
HomeBlogAbout
m3M365 NewscoMicrosoft CopilotteMicrosoft TeamsshSharePoint & OneDriveinIntune & SecurityexExchange & OutlookpoPower PlatformazAzure & Entra IDtuTutorials & GuidesevEvents & ConferencesseSecuritywiWindows
IAMinerva

Professional blog dedicated to the Microsoft 365 ecosystem.

Quick links

HomeBlogAboutNewsletter

Stay informed

Get the latest Microsoft 365 news delivered straight to your inbox.

© 2026 IAMinerva. All rights reserved.

Built withNext.js&Tailwind
Script PowerShell avancé : Rapport de modifications Microsoft 365 Groups
BlogM365 NewsAdvanced PowerShell Script: Microsoft 365 Groups Change Report
M365 News#Microsoft365Groups#PowerShell#MicrosoftGraph

Advanced PowerShell Script: Microsoft 365 Groups Change Report

Complete technical guide to create a modern PowerShell reporting script for Microsoft 365 Groups changes via Graph API and audit logs.

Houssem MAKHLOUF
April 9, 2026
6 min read

TL;DR par Minerva

généré par IA

Complete technical guide to create a modern PowerShell reporting script for Microsoft 365 Groups changes via Graph API and audit logs.

Introduction

Monitoring changes made to Microsoft 365 Groups is a critical concern for system administrators. PowerShell scripts developed several years ago require complete modernization to adapt to the architectural changes in the Microsoft 365 ecosystem. This article presents an advanced technical approach to implementing an automated group change reporting system.

!

Obsolescence of old scripts

PowerShell scripts dating from 2016 use deprecated authentication methods such as the Credential parameter for Exchange Online PowerShell, which will be removed in July 2026.

Technical architecture of the reporting system

The modern approach relies on leveraging unified audit logs rather than maintaining local XML files. This architecture offers several technical advantages:

  • Elimination of local dependencies: No need to maintain configuration files on disk
  • Centralized source of truth: Audit events provide complete history
  • Improved scalability: Compatible with Azure Automation environments
  • Enhanced security: Modern authentication via Microsoft Graph

Required technical components

The system relies on several critical PowerShell modules:

⚡PowerShell
1# Required modules for implementation
2Import-Module Microsoft.Graph.Authentication
3Import-Module Microsoft.Graph.Groups
4Import-Module ExchangeOnlineManagement
5Import-Module ImportExcel # Optional for XLSX export

Implementation of the advanced reporting script

1

Establishing secure connections

The first step is to establish authenticated connections to Microsoft APIs:

⚡PowerShell
1# Connect to Exchange Online with modern authentication
2Connect-ExchangeOnline -UseRPCEncryption
3
4# Connect to Microsoft Graph with specific permissions
5Connect-MgGraph -Scopes "Group.Read.All", "AuditLog.Read.All", "Mail.Send"
2

Retrieving Microsoft 365 Groups

Using Microsoft Graph to obtain the complete list of groups:

⚡PowerShell
1# Optimized retrieval of Microsoft 365 Groups
2$M365Groups = Get-MgGroup -Filter "groupTypes/any(c:c eq 'Unified')" -All
3
4# Create a hash table to optimize lookups
5$GroupsHashTable = @{}
6foreach ($Group in $M365Groups) {
7 $GroupsHashTable[$Group.Id] = @{
8 DisplayName = $Group.DisplayName
9 Mail = $Group.Mail
10 CreatedDateTime = $Group.CreatedDateTime
11 Visibility = $Group.Visibility
12 }
13}
3

Querying unified audit logs

Searching for audit events from the last 30 days:

⚡PowerShell
1# Define the audit period
2$StartDate = (Get-Date).AddDays(-30)
3$EndDate = Get-Date
4
5# Search for group modification events
6$AuditSearchResults = Search-UnifiedAuditLog `
7 -StartDate $StartDate `
8 -EndDate $EndDate `
9 -Operations "Add group", "Update group", "Delete group" `
10 -ResultSize 5000
11
12# Filter for Microsoft 365 Groups only
13$GroupAuditEvents = $AuditSearchResults | Where-Object {
14 $_.AuditData | ConvertFrom-Json | Where-Object {
15 $_.ModifiedProperties -contains "GroupType" -and
16 $_.ModifiedProperties.NewValue -contains "Unified"
17 }
18}
4

Processing and analyzing audit data

In-depth analysis of collected events:

⚡PowerShell
1# Initialize result collections
2$NewGroups = [System.Collections.Generic.List[PSObject]]::new()
3$UpdatedGroups = [System.Collections.Generic.List[PSObject]]::new()
4$DeletedGroups = [System.Collections.Generic.List[PSObject]]::new()
5
6# Process audit events
7foreach ($Event in $GroupAuditEvents) {
8 $AuditData = $Event.AuditData | ConvertFrom-Json
9
10 switch ($Event.Operations) {
11 "Add group" {
12 $NewGroups.Add([PSCustomObject]@{
13 GroupName = $AuditData.ObjectId
14 CreatedBy = $AuditData.UserId
15 CreationTime = $Event.CreationDate
16 ClientApplication = $AuditData.ClientApplication
17 })
18 }
19 "Update group" {
20 $UpdatedGroups.Add([PSCustomObject]@{
21 GroupName = $AuditData.ObjectId
22 ModifiedBy = $AuditData.UserId
23 ModificationTime = $Event.CreationDate
24 ModifiedProperties = $AuditData.ModifiedProperties
25 })
26 }
27 "Delete group" {
28 $DeletedGroups.Add([PSCustomObject]@{
29 GroupName = $AuditData.ObjectId
30 DeletedBy = $AuditData.UserId
31 DeletionTime = $Event.CreationDate
32 })
33 }
34 }
35}
5

Generating advanced HTML report

Creating an HTML report with professional formatting:

⚡PowerShell
1# HTML template with inline CSS
2$HTMLTemplate = @"
3<!DOCTYPE html>
4<html>
5<head>
6 <title>Microsoft 365 Groups Modification Report</title>
7 <style>
8 body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
9 .header { background-color: #0078d4; color: white; padding: 20px; }
10 .section { margin: 20px 0; }
11 table { border-collapse: collapse; width: 100%; }
12 th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
13 th { background-color: #f2f2f2; }
14 .new { background-color: #d4edda; }
15 .updated { background-color: #fff3cd; }
16 .deleted { background-color: #f8d7da; }
17 </style>
18</head>
19<body>
20 <div class="header">
21 <h1>Microsoft 365 Groups Modification Report</h1>
22 <p>Period: {0} to {1}</p>
23 </div>
24"@ -f $StartDate.ToString("yyyy-MM-dd"), $EndDate.ToString("yyyy-MM-dd")
25
26# Add data sections
27$HTMLReport = $HTMLTemplate
28$HTMLReport += "<div class='section new'><h2>New groups ({0})</h2>" -f $NewGroups.Count
29# [HTML table generation code...]
30$HTMLReport += "</body></html>"
6

Exporting data and automated sending

Finalization with export and email delivery:

⚡PowerShell
1# Export to Excel if ImportExcel module is available
2if (Get-Module -ListAvailable -Name ImportExcel) {
3 $ExportPath = "C:\Reports\M365Groups_$(Get-Date -Format 'yyyyMMdd').xlsx"
4 $NewGroups | Export-Excel -Path $ExportPath -WorksheetName "New" -AutoSize
5 $UpdatedGroups | Export-Excel -Path $ExportPath -WorksheetName "Modified" -AutoSize -Append
6 $DeletedGroups | Export-Excel -Path $ExportPath -WorksheetName "Deleted" -AutoSize -Append
7} else {
8 # Fallback to CSV
9 $ExportPath = "C:\Reports\M365Groups_$(Get-Date -Format 'yyyyMMdd').csv"
10 $AllChanges | Export-Csv -Path $ExportPath -NoTypeInformation -Encoding UTF8
11}
12
13# Send report via email using Microsoft Graph
14$Message = @{
15 Subject = "Microsoft 365 Groups Modification Report - $(Get-Date -Format 'dd/MM/yyyy')"
16 Body = @{
17 ContentType = "HTML"
18 Content = $HTMLReport
19 }
20 ToRecipients = @(
21 @{
22 EmailAddress = @{
23 Address = "admin@contoso.com"
24 }
25 }
26 )
27 Attachments = @(
28 @{
29 "@odata.type" = "#microsoft.graph.fileAttachment"
30 Name = Split-Path $ExportPath -Leaf
31 ContentBytes = [Convert]::ToBase64String([IO.File]::ReadAllBytes($ExportPath))
32 }
33 )
34}
35
36Send-MgUserMail -UserId "service@contoso.com" -Message $Message

Optimizations and performance considerations

✦

Optimizing Graph queries

For environments with many groups, implement pagination and use OData filters to reduce network load.

Delta Query API limitations

Although Microsoft Graph offers a Delta Query feature for groups, it has important limitations:

  • The PowerShell SDK does not expose the necessary delta link
  • Requires prior baseline establishment
  • Implementation complexity for marginal performance gain
⚡PowerShell
1# Example of Delta query (limited)
2# Note: Requires direct REST implementation
3$DeltaUri = "https://graph.microsoft.com/v1.0/groups/delta"

Integration with Azure Automation

The script can be easily adapted for Azure Automation with the following modifications:

Managed identity configuration

⚡PowerShell
1# Authentication via managed identity
2Connect-MgGraph -Identity
3
4# Retrieve parameters from Azure Key Vault
5$RecipientEmail = Get-AzKeyVaultSecret -VaultName "MyKeyVault" -Name "ReportRecipient" -AsPlainText

Scheduling executions

Creating a scheduled Runbook for automatic execution:

  • Recommended frequency: Weekly or monthly
  • Execution window: Off-peak hours to optimize performance
  • Error handling: Implement retry logic and alerts
MethodAdvantagesDisadvantages
Local scriptFull control, easy debuggingManual maintenance, local dependencies
Azure AutomationAutomated execution, managed identitiesConfiguration complexity, Azure costs
Azure FunctionsServerless, automatic scalingRuntime limitations, learning curve

Analysis of modification patterns

Analysis of the data reveals interesting patterns:

  • System modifications: Primarily via Office 365 Exchange Online app
  • Automated applications: Group Configuration Processor, Microsoft Approval Management
  • User actions: Generally via Teams or SharePoint Online
i

Technical insight

Automatic modifications represent approximately 70% of audit events, reflecting Microsoft 365's internal synchronization processes.

Security and compliance

Minimum required permissions

The principle of least privilege must be applied:

⚡PowerShell
1# Microsoft Graph permissions strictly necessary
2$RequiredScopes = @(
3 "Group.Read.All", # Read groups
4 "AuditLog.Read.All", # Access audit logs
5 "Mail.Send" # Send emails
6)

Sensitive data management

  • Export encryption: Using Azure Information Protection
  • Log retention: Compliance with governance policies
  • Report access: Strict RBAC control

Technical conclusion

This modernized approach for reporting Microsoft 365 Groups changes provides a robust and scalable solution. The use of Graph APIs and unified audit logs ensures superior accuracy and reliability compared to methods based on local configuration files.

The script can be downloaded from the Office 365 for IT Pros GitHub repository and adapted according to your environment's specific needs.

Share:
HM

Houssem MAKHLOUF

Microsoft 365 enthusiast & IT professional.

Previous article

Agent 365: First APIs Now Available on Microsoft Graph

Apr 7, 2026
Next article

Microsoft Tenant Governance: Introduction and Configuration

Apr 9, 2026

Related articles

Exécution de scripts PowerShell pour auditer des applications AI et gérer leurs enregistrements.copilot

Audit and Manage AI Applications with PowerShell

Audit unauthorized AI applications in Entra ID with PowerShell and Microsoft Graph to strengthen control and security.

Jun 28, 20264 min
Graphiques abstraits et géométriques avec des couches de couleurs translucides.exchange

Converting Exchange IDs for Microsoft 365 Graph API

Convert Exchange identifiers (storeId, entryId, RestId) for Graph API and targeted eDiscovery. Technical guide with complete PowerShell scripts.

Jun 28, 20267 min
Pyramide réfléchissante au centre de réseaux de fils dorés et cercles.azure

Graph Delta Queries for Entra ID Groups

Learn how to use Graph Delta Queries for Entra ID groups to track changes in real-time. Tutorials and scripts included.

Jun 27, 20264 min