Cloud Engineer Lab
Cloud Engineer Lab
Cloud Engineer Lab
Cloud Engineer Lab
© 2026
How I Automated Intune Compliance Reports Using PowerShell and Microsoft Graph
AutomationIntermediate

How I Automated Intune Compliance Reports Using PowerShell and Microsoft Graph

Every Monday morning our team needed a full compliance report from Intune. I got tired of doing it manually, so I automated the whole thing with PowerShell and Microsoft Graph API. Here is exactly how I did it.

8 min read
Share

Every Monday morning at 9am, my manager would ask the same question: "How many devices are non-compliant right now?"

For the first few weeks, I would log into the Intune admin centre, run a report, export it to Excel, clean it up, and email it across. It took about 25 minutes each time.

After doing this six times, I had enough. I automated the whole thing with PowerShell and Microsoft Graph API. Now it runs on a schedule, exports a clean report, and emails it automatically — without me touching anything.

This guide walks you through exactly how I built it.


What We Are Building

By the end of this guide, you will have a PowerShell script that:

  • Connects to Microsoft Graph API using an app registration (no interactive login)
  • Pulls all managed devices from Intune
  • Filters for non-compliant devices
  • Exports the results to a clean CSV file
  • Can be scheduled via Windows Task Scheduler or Azure Automation

You need the Microsoft.Graph PowerShell module installed. If you have not installed it yet, run: Install-Module Microsoft.Graph -Scope CurrentUser


How the Script Works: The Big Picture

Before writing a single line of code, it helps to understand the flow of what we are doing.

App Registration in Entra ID — gives the script permission to read Intune data
PowerShell connects to Microsoft Graph using Client ID + Secret
Graph API returns all managed devices from Intune
Script filters for non-compliant devices only
Results exported to CSV — ready for the manager or scheduled email

Step 1: Create an App Registration in Entra ID

The script needs permission to read Intune data. We do this through an App Registration in Microsoft Entra ID (Azure AD). This gives us a Client ID and Client Secret — like a username and password for the script.

Go to Entra ID in the Azure Portal

Open portal.azure.com, search for Entra ID, and click App registrations in the left menu.

Create a new registration

Click New registration. Give it a name like "Intune-Compliance-Reporter". Leave the default settings and click Register.

Note down your IDs

After creation, copy the Application (client) ID and the Directory (tenant) ID from the Overview page. You will need both in the script.

Create a client secret

Go to Certificates and secrets → New client secret. Set an expiry (12 months is fine). Copy the secret value immediately — it is only shown once.

Add API permissions

Go to API permissions → Add a permission → Microsoft Graph → Application permissions. Search for and add: DeviceManagementManagedDevices.Read.All. Then click Grant admin consent.

Store your Client Secret somewhere secure — like Azure Key Vault or a password manager. Never hardcode it directly in a script that gets shared or committed to GitHub.


Step 2: The PowerShell Script

Here is the full script. I will break it down section by section below.

powershell
# ── Configuration ──────────────────────────────────────────────
$TenantId     = "your-tenant-id-here"
$ClientId     = "your-client-id-here"
$ClientSecret = "your-client-secret-here"
$OutputPath   = "C:\Reports\IntuneComplianceReport.csv"
 
# ── Connect to Microsoft Graph ─────────────────────────────────
$SecureSecret = ConvertTo-SecureString $ClientSecret -AsPlainText -Force
$Credential   = New-Object System.Management.Automation.PSCredential($ClientId, $SecureSecret)
 
Connect-MgGraph -TenantId $TenantId -ClientSecretCredential $Credential
 
Write-Host "Connected to Microsoft Graph" -ForegroundColor Green
 
# ── Get all managed devices ────────────────────────────────────
Write-Host "Fetching devices from Intune..." -ForegroundColor Cyan
 
$AllDevices = Get-MgDeviceManagementManagedDevice -All -Property `
    DeviceName, ComplianceState, UserPrincipalName, OperatingSystem,
    OsVersion, LastSyncDateTime, EnrolledDateTime, Manufacturer, Model
 
Write-Host "Total devices found: $($AllDevices.Count)" -ForegroundColor Cyan
 
# ── Filter non-compliant devices ───────────────────────────────
$NonCompliant = $AllDevices | Where-Object {
    $_.ComplianceState -eq "noncompliant"
}
 
Write-Host "Non-compliant devices: $($NonCompliant.Count)" -ForegroundColor Yellow
 
# ── Build the report ───────────────────────────────────────────
$Report = $NonCompliant | Select-Object @(
    @{ Name = "Device Name";      Expression = { $_.DeviceName } },
    @{ Name = "User";             Expression = { $_.UserPrincipalName } },
    @{ Name = "OS";               Expression = { $_.OperatingSystem } },
    @{ Name = "OS Version";       Expression = { $_.OsVersion } },
    @{ Name = "Manufacturer";     Expression = { $_.Manufacturer } },
    @{ Name = "Model";            Expression = { $_.Model } },
    @{ Name = "Last Sync";        Expression = { $_.LastSyncDateTime } },
    @{ Name = "Enrolled On";      Expression = { $_.EnrolledDateTime } },
    @{ Name = "Compliance State"; Expression = { $_.ComplianceState } }
)
 
# ── Export to CSV ──────────────────────────────────────────────
$Report | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
 
Write-Host "Report saved to: $OutputPath" -ForegroundColor Green
 
# ── Disconnect ─────────────────────────────────────────────────
Disconnect-MgGraph

Breaking Down the Key Parts

Connecting Without a Pop-Up Login

The standard way to connect to Graph is Connect-MgGraph — but that opens a browser window for you to sign in. That does not work for scheduled scripts.

Instead, we use Client Secret credentials. The script authenticates silently using the App Registration we created in Step 1. No human interaction required.

powershell
$SecureSecret = ConvertTo-SecureString $ClientSecret -AsPlainText -Force
$Credential   = New-Object System.Management.Automation.PSCredential($ClientId, $SecureSecret)
Connect-MgGraph -TenantId $TenantId -ClientSecretCredential $Credential

Fetching Devices Efficiently

The -All flag on Get-MgDeviceManagementManagedDevice is important. Without it, Graph API only returns the first 1,000 devices. In a large organisation, this will silently give you incomplete data.

The -Property parameter tells Graph to return only the fields you need. This makes the API call faster and reduces the data transferred.

Filtering for Non-Compliant Devices

powershell
$NonCompliant = $AllDevices | Where-Object {
    $_.ComplianceState -eq "noncompliant"
}

The possible values for ComplianceState are:

ValueMeaning
compliantDevice meets all compliance policies
noncompliantDevice fails one or more policies
inGracePeriodDevice is non-compliant but still in the grace period
unknownDevice has not yet been evaluated
notApplicableNo compliance policy assigned to this device

You can add more filters — for example, to report only on Windows devices:

powershell
$NonCompliant = $AllDevices | Where-Object {
    $_.ComplianceState -eq "noncompliant" -and
    $_.OperatingSystem -eq "Windows"
}

Step 3: Schedule It to Run Automatically

Option A — Windows Task Scheduler (simplest)

Create a .ps1 file with the script, then set up a scheduled task to run it:

powershell
# Run this once to create the scheduled task
$Action  = New-ScheduledTaskAction -Execute "powershell.exe" `
           -Argument "-NonInteractive -File C:\Scripts\IntuneReport.ps1"
 
$Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 8am
 
Register-ScheduledTask -TaskName "IntuneComplianceReport" `
    -Action $Action -Trigger $Trigger -RunLevel Highest

Azure Automation is better for production because:

  • It runs in the cloud — no dependency on a local machine being on
  • Credentials are stored in secure Azure Key Vault
  • You get run logs and failure alerts built in

Upload the script as a Runbook, store your credentials as Automation Variables, and set a schedule from the Automation Account.

For Azure Automation, use a Managed Identity instead of a Client Secret. Managed Identities do not expire, cannot be leaked, and require no credential management. Assign the DeviceManagementManagedDevices.Read.All permission to the Managed Identity in Entra ID.


What the Output Looks Like

The CSV report includes these columns for every non-compliant device:

Device NameUserOSOS VersionManufacturerModelLast SyncCompliance State
LAPTOP-001john@company.comWindows11.0.26100DellLatitude 55402026-05-06noncompliant
IPHONE-042sara@company.comiOS17.4.1AppleiPhone 142026-05-05noncompliant

This file can go straight into an email, be opened in Excel, or be loaded into Power BI for a compliance dashboard.


Taking It Further

Once the basic script is working, here are some useful extensions:

  • Email the report automatically — use Send-MgUserMail from the Graph module to email the CSV to your team every Monday morning
  • Push data to Power BI — write the data to a Power BI streaming dataset for a live compliance dashboard
  • Trigger remediation — if a device has been non-compliant for more than 7 days, automatically send a notification to the user via Teams using the Graph API
  • Compare week over week — save each week's report and compare to see whether compliance is improving or getting worse

Summary

Automating Intune compliance reports with PowerShell and Microsoft Graph removes a repetitive manual task and gives your team accurate, consistent data every time.

The three things that made this work reliably:

  1. App registration with the right Graph permissions — no interactive login needed
  2. The -All flag — ensures you get every device, not just the first 1,000
  3. Scheduled execution — Task Scheduler or Azure Automation removes any human dependency

The script above is production-ready. Drop in your tenant ID, client ID, and client secret, and it will run straight away.

CChetan Yamger

Written by

Chetan Yamger

Cloud Engineer · AI Automation Architect · Blogger

Cloud Engineer and AI Automation Architect with deep expertise in Azure, Intune, PowerShell, and AI-driven workflows. I use ChatGPT, Gemini, and prompt engineering to build intelligent automation that improves productivity and decision-making in real IT environments.

AI AutomationAzure & IntunePowerShell & PythonNode.js / Next.jsApplication PackagingPower BIGeminiVDI / WVDGitHub ActionsM365Graph APIPrompt Engineering
Newsletter

Stay in the loop.
New articles, straight to you.

Deep-dive technical articles on Intune, PowerShell, and AI — no noise, no spam.

New article notifications
No spam, ever
Free forever

Discussion

Share your thoughts — your email stays private

Leave a comment

0/2000

Your email is used to prevent spam and will never be displayed.