smsagent.blog
Search…
Bonus! Unhealthy MEMCM Clients email report

Bonus!

As another example of how you can export data from MS Graph, below is an Azure automation Runbook you can use to generate an email report of unhealthy co-managed MEMCM clients. Specifically, it will export a list of MEMCM co-managed devices that have synced with Intune in the last 7 days but have not synced with a MEMCM management point in the last 7 days. It will then send you the list as a CSV attachment in an email.

Unhealthy MEMCM Clients runbook

Requirements

    Your automation account must be using a managed identity
    The managed identity must be granted the appropriate permissions to Microsoft Graph as described in this guide
    Outlook 365 with direct send or smtp relay configured
1
################################################################################
2
## Azure automation runbook PowerShell script to export a list of unhealthy ##
3
## MEMCM clients from Microsoft Intune / Endpoint Manager and send it the CSV ##
4
## report as an email attachment. ##
5
################################################################################
6
7
# Set some variables
8
$ProgressPreference = 'SilentlyContinue'
9
$EmailParams = @{
11
12
Smtpserver = 'contoso-com.mail.protection.outlook.com'
13
Port = 25
14
}
15
16
# Obtain an access token for MS Graph as a Managed Identity
17
$url = $env:IDENTITY_ENDPOINT
18
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
19
$headers.Add("X-IDENTITY-HEADER", $env:IDENTITY_HEADER)
20
$headers.Add("Metadata", "True")
21
$body = @{resource='https://graph.microsoft.com/' }
22
$accessToken = (Invoke-RestMethod $url -Method 'POST' -Headers $headers -ContentType 'application/x-www-form-urlencoded' -Body $body ).access_token
23
$authHeader = @{
24
'Authorization' = "Bearer $accessToken"
25
}
26
27
# Download data from MS Graph
28
$URI = "https://graph.microsoft.com/beta/deviceManagement/manageddevices?`$filter=StartsWith(operatingSystem,'Windows')&`$select=deviceName,enrolledDateTime,lastSyncDateTime,managementAgent,deviceEnrollmentType,userPrincipalName,model,serialNumber,userDisplayName,configurationManagerClientEnabledFeatures,configurationManagerClientHealthState"
29
$Response = Invoke-WebRequest -Uri $URI -Method Get -Headers $authHeader -UseBasicParsing
30
$JsonResponse = $Response.Content | ConvertFrom-Json
31
$DeviceData = $JsonResponse.value
32
If ($JsonResponse.'@odata.nextLink')
33
{
34
do {
35
$URI = $JsonResponse.'@odata.nextLink'
36
$Response = Invoke-WebRequest -Uri $URI -Method Get -Headers $authHeader -UseBasicParsing
37
$JsonResponse = $Response.Content | ConvertFrom-Json
38
$DeviceData += $JsonResponse.value
39
} until ($null -eq $JsonResponse.'@odata.nextLink')
40
}
41
42
# Organise the data as we want it displayed
43
$Devices = New-Object System.Collections.ArrayList
44
foreach ($item in $DeviceData)
45
{
46
try {
47
[void]$Devices.Add(
48
[PSCustomObject]@{
49
deviceName = $item.deviceName
50
enrolledDateTime = $item.enrolledDateTime
51
daysEnrolled = [math]::Round(((Get-Date) - ($item.enrolledDateTime | Get-Date -ErrorAction SilentlyContinue)).TotalDays,0)
52
lastSyncDateTime = $item.lastSyncDateTime
53
daysSinceLastSync = [math]::Round(((Get-Date) - ($item.lastSyncDateTime | Get-Date -ErrorAction SilentlyContinue)).TotalDays,0)
54
managementAgent = $item.managementAgent
55
deviceEnrollmentType = $item.deviceEnrollmentType
56
userPrincipalName = $item.userPrincipalName
57
model = $item.model
58
serialNumber = $item.serialNumber
59
userDisplayName = $item.userDisplayName
60
memcmEnabledFeature_inventory = $item.configurationManagerClientEnabledFeatures.inventory
61
memcmEnabledFeature_modernApps = $item.configurationManagerClientEnabledFeatures.modernApps
62
memcmEnabledFeature_resourceAccess = $item.configurationManagerClientEnabledFeatures.resourceAccess
63
memcmEnabledFeature_deviceConfiguration = $item.configurationManagerClientEnabledFeatures.deviceConfiguration
64
memcmEnabledFeature_compliancePolicy = $item.configurationManagerClientEnabledFeatures.compliancePolicy
65
memcmEnabledFeature_windowsUpdateForBusiness = $item.configurationManagerClientEnabledFeatures.windowsUpdateForBusiness
66
memcmEnabledFeature_endpointProtection = $item.configurationManagerClientEnabledFeatures.endpointProtection
67
memcmEnabledFeature_officeApps = $item.configurationManagerClientEnabledFeatures.officeApps
68
memcmClientHealth_state = $item.configurationManagerClientHealthState.state
69
memcmClientHealth_errorCode = $item.configurationManagerClientHealthState.errorCode
70
memcmClientHealth_lastSyncDateTime = $item.configurationManagerClientHealthState.lastSyncDateTime
71
memcmClientHealth_daysSinceLastSync = [math]::Round(((Get-Date) - ($item.configurationManagerClientHealthState.lastSyncDateTime | Get-Date -ErrorAction SilentlyContinue)).TotalDays,0)
72
}
73
)
74
}
75
catch {}
76
}
77
78
# Filter and export just the unhealthy clients - those that have talked to Intune but haven't talked to MEMCM in the last 7 days
79
$UnhealthyMEMCMClients = $Devices | where {$_.memcmClientHealth_state -ne 'healthy' -and $_.daysSinceLastSync -le 7 -and $_.memcmClientHealth_daysSinceLastSync -gt 7}
80
$UnhealthyMEMCMClients | export-csv -Path $env:temp\UnhealthyMEMCMClients.csv -Force -NoTypeInformation
81
82
# Send the email
83
Send-MailMessage @EmailParams -Subject "[Azure Automation] Unhealthy MEMCM Clients in Intune ($($UnhealthyMEMCMClients.Count))" -Attachments "$env:temp\UnhealthyMEMCMClients.csv"
Copied!
Last modified 5mo ago