AutopilotHealthCheck.ps1
<#PSScriptInfo
.VERSION 1.0 .GUID 3101c38e-4843-4582-b85b-a2e8cf565220 .AUTHOR Michael Niehaus .COMPANYNAME Microsoft .COPYRIGHT .TAGS Windows AutoPilot .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Version 1.0: Original published version. #> <# .SYNOPSIS Checks all devices registered with Windows Autopilot for common issues. .DESCRIPTION This script uses the Graph API to check for a variety of common issues with devices that are registered with Windows Autopilot. It leverages the WindowsAutopilotIntune, Microsoft.Graph.Intune, and AzureAD modules which should be installed (using "Install-Module") before running this script. It will be necessary to sign in twice, once to MSGraph (for access to Intune and Autopilot objects) and once to Azure AD (for additional Azure AD objects). This script does not change anything, it only reads info from the Graph and displays a simple report based on what it finds. Due to the amount of data this will retrieve, it is possible this won't work for large tenants due to Graph API throttling. .EXAMPLE .\AutopilotHealthCheck.ps1 #> Import-Module WindowsAutopilotIntune -Scope Global Import-Module AzureAD -Scope Global $intuneId = Connect-MSGraph $aadId = Connect-AzureAD # Data gathering $autopilotDevices = Get-AutopilotDevice $autopilotProfiles = Get-AutopilotProfile $aadDevices = Get-AzureADDevice -All $true $intuneDevices = Get-IntuneManagedDevice $intuneDJProfiles = (Invoke-MSGraphRequest -Url 'https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations').Value | ? {$_.'@odata.type' -eq '#microsoft.graph.windowsDomainJoinConfiguration'} # STEP 1: Report on overall status Write-Host " " Write-Host "Overall Windows Autopilot device registration status:" -ForeGroundColor Yellow Write-Host " " $autopilotDevices | Group-Object deploymentProfileAssignmentStatus | % { Write-Host "$($_.Name) : $($_.Count)" } Write-Host " " Write-Host "List of Autopilot devices with Autopilot profile assignment issues:" Write-Host " " $autopilotDevices | ? {-not ($_.deploymentProfileAssignmentStatus -eq 'assignedUnkownSyncState')} | Select serialNumber, deploymentProfileAssignmentStatus | Out-Host # STEP 2: Check device links $emptyGuid = "00000000-0000-0000-0000-000000000000" $autopilotDevices | % { $a = $_ # See if the AAD device can be found $found = $aadDevices | ? {$_.DeviceId -eq $a.azureActiveDirectoryDeviceId} if ($found) { $a | Add-Member -NotePropertyName AADStatus -NotePropertyValue Found } else { $a | Add-Member -NotePropertyName AADStatus -NotePropertyValue NotFound } # See if the Intune device can be found if ($a.managedDeviceId -eq $emptyGuid) { $a | Add-Member -NotePropertyName IntuneStatus -NotePropertyValue NeverEnrolled } else { $found = $intuneDevices | ? {$_.id -eq $a.managedDeviceId} if ($found) { $a | Add-Member -NotePropertyName IntuneStatus -NotePropertyValue Found } else { $a | Add-Member -NotePropertyName IntuneStatus -NotePropertyValue NotFound } } } Write-Host " " Write-Host "Azure AD device object status:" -ForeGroundColor Yellow Write-Host " " $autopilotDevices | Group-Object AADStatus | % { Write-Host "$($_.Name) : $($_.Count)" } Write-Host " " Write-Host "List of Autopilot devices with no corresponding Azure AD device object:" Write-Host " " $autopilotDevices | ? {$_.AADStatus -eq 'NotFound'} | Select serialNumber | Out-Host Write-Host " " Write-Host "Intune managed device object status:" -ForeGroundColor Yellow Write-Host " " $autopilotDevices | Group-Object IntuneStatus | % { Write-Host "$($_.Name) : $($_.Count)" } # STEP 3: Check profiles $autopilotProfiles | % { $type = 'Unknown' $profileName = $_.displayName if ($_.'@odata.type' -eq '#microsoft.graph.azureADWindowsAutopilotDeploymentProfile') { if ($_.outOfBoxExperienceSettings.deviceUsageType -eq 'shared') { $type = 'SelfDeploying' } else { $type = 'UserDrivenAAD' } } elseif ($_.'@odata.type' -eq '#microsoft.graph.activeDirectoryWindowsAutopilotDeploymentProfile') { $type = 'UserDrivenAD' } $_ | Get-AutopilotProfileAssignedDevice | % { $assignedDevice = $_ $autopilotDevices | ? {$_.id -eq $assignedDevice.id} | % { $_ | Add-Member -NotePropertyName ProfileType -NotePropertyValue $type $_ | Add-Member -NotePropertyName ProfileName -NotePropertyValue $profileName } } } Write-Host " " Write-Host "Autopilot devices by profile type:" -ForeGroundColor Yellow Write-Host " " $autopilotDevices | ? {$_.ProfileType} | Group-Object ProfileType | % { Write-Host "$($_.Name) : $($_.Count)" } # STEP 4: Check if AD devices have a domain join profile $autopilotDevices | % { $_ | Add-Member -NotePropertyName HasDJProfile -NotePropertyValue $false } $intuneDJProfiles | % { $dj = $_ (Get-IntuneDeviceConfigurationPolicyAssignment -deviceConfigurationId $_.id).target | % { if ($_.'@odata.type' -eq '#microsoft.graph.allDevicesAssignmentTarget') { $autopilotDevices | % { $_.HasDJProfile = $true } } else { $devices = Invoke-MSGraphRequest -Url "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations/$($dj.id)/deviceStatuses" $devices.value | % { $managedDeviceId = $_.id.Substring(74) $intuneDevices | ? {$_.id -eq $managedDeviceId } | % { $aadId = $_.azureADDeviceId $autopilotDevices | ? {$_.azureActiveDirectoryDeviceId -eq $aadId} | % { $_.HasDJProfile = $true } } } } } } Write-Host " " Write-Host "Autopilot Hybrid AADJ domain join profile check:" -ForeGroundColor Yellow Write-Host " " $result = $autopilotDevices | ? {$_.ProfileType -eq 'UserDrivenAD'} | Group-Object HasDJProfile $result | % { Write-Host "$($_.Name) : $($_.Count)" } Write-Host " " Write-Host "List of Autopilot Hybrid AADJ devices with no domain join profile:" Write-Host " " $result | ? {$_.Name -eq $false} | % { $_.Group } | Select serialNumber, azureActiveDirectoryDeviceId, managedDeviceId, enrollmentState | Out-Host |