PowerShell两个PSCustomObject为null时报Cannot index into a null array如何解决
问题根因
报错核心来自两个问题:
$ADResult和$GResult类型不统一:无数据时你赋值为单个PSCustomObject,有数据时是数组,访问属性的行为完全不一致- 直接用索引访问属性时没有做空兼容,一旦对象为空或者属性不是数组,就会触发空数组索引错误
优化方案
步骤1:统一$ADResult和$GResult的结构
不管有没有查询到数据,都将两个变量固定为PSCustomObject数组,每个数组元素对应一条组数据,无数据时填充一条空属性的元素,保证数组长度至少为1,避免后续循环不执行丢失基础字段。
优化后的$ADResult处理逻辑:
$ADResult = @() if ([string]::IsNullOrWhiteSpace($ADGroups)) { Write-Warning "No AD Groups" # 无数据时往数组里加一个空属性对象 $ADResult += [PSCustomObject]@{ ADGroups = "" ADGroupsdistinguishedName = "" } } else { foreach ($group in $ADGroups) { # 保留你原有的group处理逻辑,处理完把结果追加到数组 $ADResult += [PSCustomObject]@{ ADGroups = $group.Name # 替换为你实际的取值逻辑 ADGroupsdistinguishedName = $group.DistinguishedName # 替换为你实际的取值逻辑 } } }
$GResult的初始化逻辑和上面完全对齐,确保永远是数组,无数据时也包含一个空元素。
步骤2:优化整合代码的空兼容处理
取值时用PowerShell的空条件运算符?.和空合并运算符??做兼容,就算索引越界或者属性为空,也会返回空字符串而不报错,同时保证就算两个组数组都为空,也会生成1条包含基础字段的记录。
优化后的整合代码:
# 取两个数组的最大长度,最小为1,保证至少循环一次,不会丢失基础字段 [int]$max = [Math]::Max($ADResult.Count, $GResult.Count) $max = [Math]::Max($max, 1) # 直接用循环输出赋值比$Result += 追加性能高很多 $Result = for ( $i = 0; $i -lt $max; $i++) { [PSCustomObject]@{ PrimaryEmail = $email Title = $UserInfo.title Department = $UserInfo.Department Manager = $Manager EmailBackup = $ENV:Backup AccountDisabled = $ENV:ADDisabled GoogleRemoved = $ENV:RemoveGoogle # 空兼容取值:索引不存在就返回空字符串 ADGroupName = $ADResult[$i]?.ADGroups ?? "" ADGroupNameDistinguishedName = $ADResult[$i]?.ADGroupsdistinguishedName ?? "" GoogleGroup = $GResult[$i]?.GoogleGroups ?? "" Role = $GResult[$i]?.role ?? "" DateOfSeparation = (Get-Date).ToString("yyyy_MM_dd") UnixID = $unix UserDistinguishedName = $UserInfo.distinguishedName UserOU = $UserInfo.Ou # 同样给PrimaryGroup加空兼容,避免primaryGroup为空时报错 PrimaryGroup = $UserInfo.primaryGroup?.Split('=').Split(',')[1] ?? "" } }
如果你使用的是PowerShell 2.0等不支持空条件运算符的旧版本,可以把取值逻辑替换为传统判断写法:
ADGroupName = if ($ADResult[$i] -and $ADResult[$i].ADGroups) { $ADResult[$i].ADGroups } else { "" }
内容的提问来源于stack exchange,提问作者dcaz
相关产品推荐
相关产品推荐

