{"id":9636,"date":"2026-05-11T10:39:28","date_gmt":"2026-05-11T10:39:28","guid":{"rendered":"https:\/\/pariswells.com\/blog\/?p=9636"},"modified":"2026-05-11T10:39:29","modified_gmt":"2026-05-11T10:39:29","slug":"script-to-get-list-of-machines-not-enrolled-into-intune-but-enrolled-into-defender","status":"publish","type":"post","link":"https:\/\/pariswells.com\/blog\/research\/script-to-get-list-of-machines-not-enrolled-into-intune-but-enrolled-into-defender","title":{"rendered":"Script to get list of Machines not enrolled into Intune but enrolled into Defender"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code class=\"\">&lt;#\n.SYNOPSIS\n    Gets all Defender onboarded devices NOT enrolled in Intune.\n    Filter by platform: \"Windows11\", \"iOS\", \"Android\", \"macOS\", \"\" (blank = all)\n\n.REQUIREMENTS\n    Install-Module Microsoft.Graph -Scope CurrentUser\n#>\n\n# ?? Configuration\n$ExportCSV      = $true\n$FilterPlatform = \"Windows11\"  # Change to \"iOS\", \"Android\", \"macOS\" or \"\" for all\n$ExportPath     = \".\\DefenderNotInIntune_${FilterPlatform}_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv\"\n\n# ?? Login\nWrite-Host \"Opening browser for login...\" -ForegroundColor Cyan\n\nConnect-MgGraph -Scopes @(\n    \"DeviceManagementManagedDevices.Read.All\",\n    \"SecurityEvents.Read.All\",\n    \"ThreatHunting.Read.All\"\n) -NoWelcome\n\nWrite-Host \"  Logged in as : $((Get-MgContext).Account)\" -ForegroundColor Green\nWrite-Host \"  Tenant       : $((Get-MgContext).TenantId)\" -ForegroundColor Green\n\n# ?? Step 1: Get all Defender machines via Advanced Hunting\nWrite-Host \"`nFetching Defender onboarded devices via Advanced Hunting...\" -ForegroundColor Cyan\n\n$mdeLookup = @{}\n\n$huntingBody = @{\n    Query = @\"\nDeviceInfo\n| where isnotempty(AadDeviceId)\n| summarize arg_max(Timestamp, *) by AadDeviceId\n| project AadDeviceId, DeviceName, OSPlatform, OSVersion, OnboardingStatus, LoggedOnUsers\n\"@\n} | ConvertTo-Json\n\ntry {\n    $huntingResponse = Invoke-MgGraphRequest `\n        -Uri \"https:\/\/graph.microsoft.com\/v1.0\/security\/runHuntingQuery\" `\n        -Method POST `\n        -Body $huntingBody `\n        -ContentType \"application\/json\" `\n        -ErrorAction Stop\n\n    foreach ($row in $huntingResponse.results) {\n        if ($row.AadDeviceId) {\n\n            # Extract last logged on user from LoggedOnUsers JSON array\n            $lastUser = $null\n            if ($row.LoggedOnUsers) {\n                try {\n                    $users = $row.LoggedOnUsers | ConvertFrom-Json -ErrorAction SilentlyContinue\n                    if ($users -and $users.Count -gt 0) {\n                        $lastUser = \"$($users[0].DomainName)\\$($users[0].UserName)\"\n                    }\n                } catch {\n                    $lastUser = $row.LoggedOnUsers\n                }\n            }\n\n            $mdeLookup[$row.AadDeviceId.ToLower()] = [PSCustomObject]@{\n                DeviceName       = $row.DeviceName\n                OSPlatform       = $row.OSPlatform\n                OSVersion        = $row.OSVersion\n                OnboardingStatus = $row.OnboardingStatus\n                LastLoggedOnUser = $lastUser\n            }\n        }\n    }\n    Write-Host \"  Found $($mdeLookup.Count) Defender onboarded devices\" -ForegroundColor Green\n}\ncatch {\n    Write-Error \"Advanced Hunting failed: $_\"\n    Disconnect-MgGraph\n    exit 1\n}\n\nif ($mdeLookup.Count -eq 0) {\n    Write-Error \"No Defender devices returned. Check ThreatHunting.Read.All is consented.\"\n    Disconnect-MgGraph\n    exit 1\n}\n\n# ?? Step 2: Get all Intune enrolled device AAD IDs\nWrite-Host \"Fetching Intune enrolled devices...\" -ForegroundColor Cyan\n\n$intuneAadIds = [System.Collections.Generic.HashSet[string]]::new()\n$uri = \"https:\/\/graph.microsoft.com\/v1.0\/deviceManagement\/managedDevices?\" +\n       \"`$select=azureADDeviceId&amp;`$top=999\"\n\ndo {\n    $response = Invoke-MgGraphRequest -Uri $uri -Method GET\n    foreach ($device in $response.value) {\n        if ($device.azureADDeviceId) {\n            $null = $intuneAadIds.Add($device.azureADDeviceId.ToLower())\n        }\n    }\n    $uri = $response.'@odata.nextLink'\n} while ($uri)\n\nWrite-Host \"  Found $($intuneAadIds.Count) Intune devices\" -ForegroundColor Green\n\n# ?? Step 3: Find Defender devices NOT in Intune\nWrite-Host \"`nComparing...\" -ForegroundColor Cyan\n\n$results = foreach ($aadId in $mdeLookup.Keys) {\n    if ($aadId -notin $intuneAadIds) {\n        $defender = $mdeLookup[$aadId]\n        [PSCustomObject]@{\n            DeviceName       = $defender.DeviceName\n            OSPlatform       = $defender.OSPlatform\n            OSVersion        = $defender.OSVersion\n            OnboardingStatus = $defender.OnboardingStatus\n            LastLoggedOnUser = if ($defender.OSPlatform -like \"Windows*\") { $defender.LastLoggedOnUser } else { \"N\/A\" }\n            AzureADDeviceId  = $aadId\n        }\n    }\n}\n\n# ?? Apply platform filter\nif ($FilterPlatform) {\n    $filtered = $results | Where-Object { $_.OSPlatform -eq $FilterPlatform }\n} else {\n    $filtered = $results\n}\n\n# ?? Output\nWrite-Host \"`n================================================\" -ForegroundColor Yellow\nWrite-Host \"  Defender onboarded devices : $($mdeLookup.Count)\"    -ForegroundColor White\nWrite-Host \"  Intune enrolled devices    : $($intuneAadIds.Count)\"  -ForegroundColor White\nWrite-Host \"  In Defender NOT in Intune  : $($results.Count)\"       -ForegroundColor Red\nif ($FilterPlatform) {\nWrite-Host \"  Filtered ($FilterPlatform)  : $($filtered.Count)\"     -ForegroundColor Yellow\n}\nWrite-Host \"================================================\" -ForegroundColor Yellow\n\n$filtered | Format-Table DeviceName, OSPlatform, OSVersion, LastLoggedOnUser, AzureADDeviceId -AutoSize\n\nif ($ExportCSV -and $filtered.Count -gt 0) {\n    $filtered | Export-Csv -Path $ExportPath -NoTypeInformation -Encoding UTF8\n    Write-Host \"`nExported to: $ExportPath\" -ForegroundColor Green\n} elseif ($filtered.Count -eq 0) {\n    Write-Host \"`nNo devices found for platform: $FilterPlatform\" -ForegroundColor Green\n}\n\nWrite-Host \"`nBreakdown by OS (all platforms):\" -ForegroundColor Cyan\n$results | Group-Object OSPlatform | Sort-Object Count -Descending | Format-Table Name, Count -AutoSize\n\nDisconnect-MgGraph<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-9636","post","type-post","status-publish","format-standard","hentry","category-research"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/9636","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/comments?post=9636"}],"version-history":[{"count":1,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/9636\/revisions"}],"predecessor-version":[{"id":9637,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/9636\/revisions\/9637"}],"wp:attachment":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/media?parent=9636"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/categories?post=9636"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/tags?post=9636"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}