As we showed in the recent Recast Automation webinar, an Azure Automation runbook makes it simple to build proactive alerts for Intune. In this blog post, I’ll show you step-by-step how to deploy a script into Azure Automation.
Prerequisites
Before we begin, make sure you have:
- An Azure subscription with permissions to create Automation Accounts.
- The Monitor-IntuneAppInstallationErrors.ps1 script (see below).
Create Automation Account and Enable Managed Identity
For detailed steps on creating an Automation Account, see my earlier post.
Here’s the short version:
- Search for “Automation Accounts” in the Azure Portal.
- Click + Create, choose your Subscription and Resource Group, give it a name (e.g. intune-automation), and pick a Region.
- In the Identity tab, toggle System‑assigned managed identity to On, then select Save.
You can deploy the same resources with Terraform; I’ll cover that in an upcoming post.
Import Required Modules
Under your new Automation Account:
- Navigate to Modules > + Add a module.
- Select PowerShell Gallery.
- Search for and install:
- Az.Accounts
- Az.Resources
- Microsoft.Graph.Authentication
- Microsoft.Graph.Mail
These modules enable managed‑identity sign‑in and Microsoft Graph API calls.

Configure Automation Variables
I store the script parameters in Terraform so thresholds and email settings can be changed without editing code; you can also add the variables manually in the Automation Account.
This is my Terraform template:
resource "azurerm_automation_variable_int" "error_threshold" {
name = "ErrorThreshold"
resource_group_name = azurerm_resource_group.rg.name
automation_account_name = azurerm_automation_account.automation.name
value = "10"
}
resource "azurerm_automation_variable_int" "days_back" {
name = "DaysBack"
resource_group_name = azurerm_resource_group.rg.name
automation_account_name = azurerm_automation_account.automation.name
value = "7"
}
resource "azurerm_automation_variable_string" "sender_email" {
name = "SenderEmail"
resource_group_name = azurerm_resource_group.rg.name
automation_account_name = azurerm_automation_account.automation.name
value = "[email protected]"
}
resource "azurerm_automation_variable_string" "recipient_email" {
name = "RecipientEmail"
resource_group_name = azurerm_resource_group.rg.name
automation_account_name = azurerm_automation_account.automation.name
value = "[email protected]"
}
This is how you can add them via the portal:

Import, Publish, and Link the Runbook
- In Runbooks, select + Create a runbook.
- Enter:
- Name: Monitor-IntuneAppInstallationErrors
- Runbook type: PowerShell
- Runtime: 7.2
- Choose Edit, paste in the full contents of Monitor‑IntuneAppInstallationErrors.ps1 (shown below), and select Save.
- Click Publish to make it available.
# ==============================================
# Monitor-IntuneAppInstallationErrors.ps1
# ==============================================
try {
$ErrorThreshold = Get-AutomationVariable -Name "ErrorThreshold" -ErrorAction Stop
} catch {
$ErrorThreshold = 10
}
try {
$DaysBack = Get-AutomationVariable -Name "DaysBack" -ErrorAction Stop
} catch {
$DaysBack = 7
}
Connect-AzAccount -Identity -ErrorAction Stop
$token = (Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com").Token
$hdr = @{ Authorization = "Bearer $token"; "Content-Type" = "application/json" }
# Email variables
try { $senderEmail = Get-AutomationVariable -Name "SenderEmail" } catch { $null }
try { $recipientEmail = Get-AutomationVariable -Name "RecipientEmail" } catch { $null }
$end = Get-Date
$start = $end.AddDays(-$DaysBack)
# Build request
$requestBody = @{
top = 50; skip = 0;
select = @("DisplayName","Publisher","Platform","AppVersion","FailedDevicePercentage","FailedDeviceCount","InstalledDeviceCount");
orderBy = @("FailedDevicePercentage desc")
} | ConvertTo-Json -Depth 3
$response = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/deviceManagement/reports/getAppsInstallSummaryReport" `
-Method POST -Headers $hdr -Body $requestBody
# Process rows into objects
$report = $allApps | Where-Object { $_.ErrorRate -ge $ErrorThreshold } | Sort ErrorRate -Descending
$top5 = $allApps | Sort InstalledCount -Descending | Select -First 5
# Build HTML & send email if configured
if ($senderEmail -and $recipientEmail) {
# Construct $html and $subject based on $report.Count…
Invoke-RestMethod -Method POST -Uri "https://graph.microsoft.com/v1.0/users/$senderEmail/sendMail" `
-Headers $hdr -Body ($BodyJsonsend) -ContentType "application/json"
}
Schedule and Test the Runbook
- Back in Runbook, select Start in the Test pane to verify that it runs successfully. Review the output for any errors or warnings.
- When the test succeeds, open Schedules > + Add a schedule.
- Create a new schedule:
- Name: Daily-IntuneAppErrorCheck
- Recurrence: Daily, every 1 day, at 07:00 AM (your local).
- Link the schedule to the runbook.
Verify Alerts and Logs
- Open Jobs under the runbook to review past runs, exit codes, and output.
- If errors exceed the threshold, you should receive an email from your configured sender to the recipient.
- Fine‑tune the ErrorThreshold or DaysBack variables in Terraform, then re‑apply the configuration as needed.
Conclusion: Runbook to Monitor Intune App‑Installation Errors Deployed
Congratulations! You now have a fully automated monitoring solution for Intune app‑installation errors built with Azure Automation runbooks, Terraform‑managed configuration, and Microsoft Graph API calls—all building on what we covered in the Recast Automation webinar.