PowerShell中Add-Member偶发‘Index out of bounds’错误原因咨询
PowerShell中Add-Member抛出“索引超出数组范围”错误的原因及解决
问题描述
有人能解释为何以下PowerShell代码中的Add-Member行偶尔会抛出‘Index out of bounds’(索引超出数组范围)错误吗?该行并未涉及数组操作。
注:完整代码功能更多,此为片段,
Add-Member执行前$skus和$allusers未被修改
代码片段
$licinfo = [System.Collections.ArrayList]@() $skus = Get-MgSubscribedSku -all $allusers = get-mguser -Property userprincipalname foreach ($u in $allusers) { $obj = [pscustomobject][ordered]@{ upn = $u.userprincipalname } foreach ($sku in $skus) { $obj | Add-Member -MemberType NoteProperty -Name $sku.skuPartNumber -Value 0 } $licinfo.add($obj) | Out-Null }
错误信息
Index was outside the bounds of the array. At line:142 char:7 + $obj | Add-Member -MemberType NoteProperty -Name $sku.skuPartNu ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (:) [], IndexOutOfRangeException + FullyQualifiedErrorId : System.IndexOutOfRangeException ScriptStackTrace: at <ScriptBlock>, <No file>: line 142 System.IndexOutOfRangeException: Index was outside the bounds of the array. at lambda_method(Closure , Object[] , StrongBox`1[] , InterpretedFrame )
原因分析
这个错误并非Add-Member直接操作数组导致,而是PowerShell处理基于有序字典([ordered])的自定义对象时的底层bug,或特殊属性名触发的异常:
- 你通过
[pscustomobject][ordered]@{}创建的对象,底层依赖有序字典实现。在循环中用Add-Member动态批量添加属性时,PowerShell对有序字典的索引管理可能出现罕见越界问题。 - 少数情况下,
$sku.skuPartNumber如果是空值、包含特殊字符或不符合PowerShell属性命名规则,可能触发底层数组操作的异常。
解决方法
1. 避免事后用Add-Member给有序字典对象加属性
提前构建有序字典并一次性转换为自定义对象,跳过Add-Member步骤:
$licinfo = [System.Collections.ArrayList]@() $skus = Get-MgSubscribedSku -all $allusers = get-mguser -Property userprincipalname foreach ($u in $allusers) { $dict = [ordered]@{ upn = $u.userprincipalname } foreach ($sku in $skus) { $dict[$sku.skuPartNumber] = 0 } $obj = [pscustomobject]$dict $licinfo.add($obj) | Out-Null }
2. 改用普通无序字典创建对象
如果不需要严格的属性顺序,直接用普通字典创建对象,避免有序字典的底层bug:
$obj = [pscustomobject]@{ upn = $u.userprincipalname }
3. 校验属性名有效性
添加属性前过滤掉无效的skuPartNumber,避免异常命名触发问题:
foreach ($sku in $skus) { $skuName = $sku.skuPartNumber if (-not [string]::IsNullOrWhiteSpace($skuName) -and $skuName -match '^[a-zA-Z0-9_]+$') { $obj | Add-Member -MemberType NoteProperty -Name $skuName -Value 0 } }
4. 升级PowerShell版本
该底层bug大概率在PowerShell 7.x系列中已修复,若当前使用Windows PowerShell 5.1,建议升级到较新的PowerShell版本。
内容的提问来源于stack exchange,提问作者Haruka Shitou
相关产品推荐
相关产品推荐

