PowerShell中ArrayList致返回结果含索引值的原因排查
问题分析与解决方案
这个问题我很熟悉,根源其实出在System.Collections.ArrayList的Add()方法特性上,结合PowerShell的输出机制导致了这个意外结果:
为什么会出现额外的数字输出?
PowerShell函数默认会返回所有未被捕获或抑制的输出内容。而ArrayList的Add()方法每次执行时,都会返回当前元素被添加后的索引值(比如第一次添加返回0,第二次返回1,以此类推)。
看你代码里的这行:
$bullets.Add($bullet)
你没有对这个返回值做任何处理,所以这些索引值(0、1、2、3、4)会被悄悄加入到函数的输出流中。最后当函数返回$siteChosen时,这些额外的数字就会和站点对象一起被输出,也就是你看到的0 1 2 3 4 5 Name HubSiteEnabled Site1 False这种奇怪的结果。
而改用普通数组时,比如$bullets += $bullet这种写法,不会产生任何额外的返回值,所以函数只会返回你预期的站点对象。
两种快速解决方法
方法1:抑制Add()的返回值
最简单的方式就是把Add()的返回值捕获到$null里,或者用Out-Null丢弃:
# 方式一:赋值给$null(推荐,性能更好) $null = $bullets.Add($bullet) # 方式二:用Out-Null抑制输出 $bullets.Add($bullet) | Out-Null
修改后的完整函数代码:
function SiteChoiceMenu { $sites = Get-ExchangeServer | ForEach-Object {Get-ADSite $_.Site} | Sort-Object -Unique $siteCount = $sites.count $bullets = New-Object -TypeName System.Collections.ArrayList($null) for ($i=0;$i -lt $siteCount;$i++) { $index = $i+1 $bullet = "$index. " + $sites[$i].Name $null = $bullets.Add($bullet) # 捕获返回值,避免额外输出 } foreach ($bullet in $bullets) {Write-Host $bullet} $siteChoice = Read-Host "Enter choice" if ($siteChoice -in 1..$siteCount) { $siteChosen = $sites[$siteChoice-1]; return $siteChosen } } $siteChosen
方法2:改用PowerShell原生的泛型列表
如果你想保留动态集合的特性,推荐使用[System.Collections.Generic.List[string]]——它的Add()方法默认不会返回任何值,自然也就不会产生额外输出:
function SiteChoiceMenu { $sites = Get-ExchangeServer | ForEach-Object {Get-ADSite $_.Site} | Sort-Object -Unique $siteCount = $sites.count $bullets = [System.Collections.Generic.List[string]]::new() # 改用泛型列表 for ($i=0;$i -lt $siteCount;$i++) { $index = $i+1 $bullet = "$index. " + $sites[$i].Name $bullets.Add($bullet) # 此方法无返回值,无需额外处理 } foreach ($bullet in $bullets) {Write-Host $bullet} $siteChoice = Read-Host "Enter choice" if ($siteChoice -in 1..$siteCount) { $siteChosen = $sites[$siteChoice-1]; return $siteChosen } } $siteChosen
验证修改效果
调整后再运行脚本,$siteChosen就只会输出你选中的AD站点的详细信息,不会再夹杂那些多余的索引数字了。
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

