How to Get All Installed Apps on Devices from Intune
Table of content
Learn how to pull a complete list of installed apps from Intune—step by step, with Intune console, PowerShell and Graph API.
Prerequisites
Before you start, make sure you have:
-
An Intune Administrator account with access to Apps > Monitor > Discovered Apps Microsoft Learn.
-
PowerShell 7+ and the Microsoft.Graph.Intune module (for automation) Microsoft Learn.
-
(Optional) An Azure AD app registration with the right Graph permissions if you plan to call the Graph API directly Microsoft Learn.
Method 1: Quick CSV Export (Intune Portal)
-
Sign in to the Microsoft Endpoint Manager admin center.
-
Navigate to Apps > Monitor > Discovered apps.
-
Click Export to download a .csv report containing:
-
Application name
-
Platform
-
Version
-
Publisher
-
Device count
-
Wow, That’s it—a one-click inventory, perfect for quick audits. Also, if you need the result for specific application, just search with App name.
Method 2: Automate with PowerShell
Automating your export means you’ll never click the portal again. This script will connect to Microsoft Intune using Graph API and fetch all the installed application on all devices and will export to C:\ drive.
# Define Azure AD and App Details
$ClientID = "d86a2d7c-25c4-1111-9521-1bfe52cde8f6"
$ClientSecret = 'wB38Q~zqG1MuK.IEehNp.DnzPxr8iXVRnAfFNdnd'
$TenantID = "e869957b-68cc-4373-1111-ff5d9b56ab9c"
$RequestTimeout = 120 # Request timeout in seconds
# Start local log transcript
$LogFilePath = Join-Path $PSScriptRoot "C:\Test.log"
Start-Transcript -Path $LogFilePath
# Get Access Token
$TokenUrl = "https://login.microsoftonline.com/$TenantID/oauth2/v2.0/token"
$TokenBody = @{
Client_Id = $ClientID
Scope = "https://graph.microsoft.com/.default"
Client_Secret = $ClientSecret
Grant_Type = "client_credentials"
}
$TokenResponse = Invoke-RestMethod -Uri $TokenUrl -Method Post -Body $TokenBody -TimeoutSec $RequestTimeout
$AccessToken = $TokenResponse.Access_Token
# Define Headers for Graph API
$Headers = @{
Authorization = "Bearer $AccessToken"
}
# Query Microsoft Graph API for Managed Devices
$BaseUrl = "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices"
$Filter = "`$filter=operatingSystem+eq+'Windows'"
$ApiUrl = $BaseUrl + '?' + $Filter
Function Invoke-WithRetry {
Param (
[ScriptBlock]$ScriptBlock,
[Int]$MaxRetries = 5,
[Int]$TimeoutSec = 60
)
$RetryCount = 0
Do {
Try {
Return & $ScriptBlock
}
Catch {
$IsThrottled = $_.Exception.Response.StatusCode -eq 'TooManyRequests' -or $_.Exception.Response.StatusCode -eq '429'
$IsConnectionClosed = $_.Exception.Message -like "*unexpected EOF or 0 bytes from the transport stream*"
If ($IsThrottled -or $IsConnectionClosed) {
$RetryCount++
$BaseWaitTime = If ($_.Exception.Response.Headers['Retry-After']) {
$_.Exception.Response.Headers['Retry-After']
}
Else { [Math]::Pow(2, $RetryCount) }
# Adding randomness to the wait time
$WaitTime = $BaseWaitTime + (Get-Random -Minimum 1 -Maximum 5)
Write-Host "Request throttled or connection closed. Retrying in $WaitTime seconds..."
Start-Sleep -Seconds $WaitTime
}
Else {
Throw $_
}
}
} While ($RetryCount -lt $MaxRetries)
Throw "Maximum number of retries reached."
}
# Fetch the devices (Filter for Windows Devices)
$ManagedDevicesResponse = @()
$Top = "`$top=100"
$NextPageUrl = $ApiUrl + '&' + $Top
Do {
Write-Host "Querying URL: $NextPageUrl"
$Response = Invoke-WithRetry -ScriptBlock {
Invoke-RestMethod -Uri $NextPageUrl -Headers $Headers -TimeoutSec $RequestTimeout
} -TimeoutSec $RequestTimeout
$ManagedDevicesResponse += $Response.Value
$NextPageUrl = $Response."@odata.nextLink"
} While ($NextPageUrl)
# Loop Through Devices and Retrieve Information
$ReportData = @()
$TotalDevices = $ManagedDevicesResponse.Count
$Counter = 0
ForEach ($Device in $ManagedDevicesResponse) {
try {
$Counter++
Write-Progress -Activity "Processing Devices" -Status "$Counter of $TotalDevices" -PercentComplete (($Counter / $TotalDevices) * 100)
$DeviceId = $Device.Id
# Define the URL for fetching detected apps for this device
$DetectedAppsUrl = "https://graph.microsoft.com/beta/deviceManagement/managedDevices/$DeviceId/detectedApps"
Write-Host "Fetching apps for DeviceId $DeviceId."
# Fetch all detected apps for this device
$InstalledApps = @()
Do {
$Response = Invoke-WithRetry -ScriptBlock {
Invoke-RestMethod -Uri $DetectedAppsUrl -Headers $Headers -TimeoutSec 60
}
If ($Response.Value) {
$InstalledApps += $Response.Value
}
$DetectedAppsUrl = $Response.'@odata.nextLink'
} While ($DetectedAppsUrl)
Write-Host "Apps detected on device $DeviceId : $($InstalledApps.Count)"
# Filter Apps Containing "powerbi" and Add to Report Data
$MatchingApps = $InstalledApps | Where-Object { $_.DisplayName -like "**" }
Write-Host "Apps containing 'powerbi' on device $DeviceId : $($MatchingApps.Count)"
ForEach ($App in $MatchingApps) {
$ReportData += [PSCustomObject]@{
UserPrincipalName = $Device.UserPrincipalName
DeviceName = $Device.DeviceName
Manufacturer = $Device.Manufacturer
Model = $Device.Model
OperatingSystem = $Device.OperatingSystem
AppName = $App.DisplayName
AppVersion = $App.Version
}
}
}
catch {
Write-Host "An error occurred processing device $DeviceId. Error: $($_.Exception.Message)"
continue
}
}
# Sort the Report Data
$SortedReportData = $ReportData | Sort-Object DeviceName, UserPrincipalName, AppName, AppVersion, OperatingSystem
# Export Sorted Report Data to CSV
$CurrentDate = Get-Date -Format "MM-dd-yyyy"
$CsvPath = "C:\AllIntuneDiscoveredApps-$CurrentDate.csv"
$SortedReportData | Export-Csv -Path $CsvPath -NoTypeInformation
After this Powershell Graph API script is ran, All the applications installed on devices will be exported to the CSV, you can use this script in Power BI too if you need the live dashboard. You can run this script as Windows task scheduler job to get daily email to your inbox.
Wrapping up
Well, that’s your complete toolkit to get all installed apps on devices from Intune—portal, PowerShell, or Graph API. Here’s what I think: pick the method that fits your workflow, automate it, and never miss a single app again.
For more hands-on Intune guides, swing by techeuc.com and subscribe for updates. If you need any help or facing any issues, Please reach out to me or contact me.
July 16, 2025 @ 8:17 pm
I like this blog very much so much good info .