如何高效从Azure Graph的$Devices中移除Autopilot设备?
高效筛选Azure AD中不属于Autopilot的设备
需求场景
通过Graph API获取两类设备数据:
- 用
$Devices = Get-MgDevice获取所有Azure AD设备 - 用
$autopilot = Get-MgDeviceManagementWindowsAutopilotDeviceIdentity获取所有Autopilot注册设备
需要从$Devices中移除属于Autopilot的设备,匹配依据是Autopilot设备的AzureActiveDirectoryDeviceId字段,对应Azure AD设备的Id或DeviceId字段。
低效的遍历尝试(不推荐)
如果用循环逐个比对,写法简单但数据量大时性能极差,示例如下:
$nonAutopilotDevices = @() foreach ($device in $Devices) { $isAutopilot = $false foreach ($apDevice in $autopilot) { if ($device.Id -eq $apDevice.AzureActiveDirectoryDeviceId) { $isAutopilot = $true break } } if (-not $isAutopilot) { $nonAutopilotDevices += $device } }
失败的Where-Object+-notcontains写法
直接用数组的-notcontains运算符虽然代码简洁,但每次筛选都要遍历整个Autopilot数组,数据量越大效率越低,且容易因字段匹配错误导致结果不准确:
# 性能差且可能因字段匹配错误失效的写法 $nonAutopilotDevices = $Devices | Where-Object { $autopilot.AzureActiveDirectoryDeviceId -notcontains $_.Id }
高效的哈希表实现方案
利用哈希表O(1)的查找效率,先把Autopilot设备的ID存入哈希表,再快速筛选目标设备:
# 获取基础数据 $Devices = Get-MgDevice $autopilot = Get-MgDeviceManagementWindowsAutopilotDeviceIdentity # 构建Autopilot设备ID哈希表(去重+快速查找) $autopilotDeviceHash = @{} foreach ($apDevice in $autopilot) { if (-not [string]::IsNullOrEmpty($apDevice.AzureActiveDirectoryDeviceId)) { $autopilotDeviceHash[$apDevice.AzureActiveDirectoryDeviceId] = $true } } # 快速筛选非Autopilot设备(匹配Id字段,若需匹配DeviceId则替换为$_.DeviceId) $nonAutopilotDevices = $Devices | Where-Object { -not $autopilotDeviceHash.ContainsKey($_.Id) }
方案优势
- 哈希表的
ContainsKey方法查找耗时固定,不受数据量增长影响 - 提前预处理Autopilot设备ID,避免重复遍历数组
- 自动过滤空ID的无效数据,提升结果准确性
内容的提问来源于stack exchange,提问作者Xrai
相关产品推荐
相关产品推荐

