PowerShell脚本ForEach循环遍历文件时提前终止问题求助
问题分析与修复方案
核心问题:循环提前终止
你的脚本在catch块中使用了return语句,这会直接退出整个函数,导致ForEach循环仅处理第一个触发异常的条目就停止执行。
其他潜在问题
- Select-Object语法错误:
Select-Object UserName = $lname是无效语法,无需额外赋值,直接指定属性名即可。 - 错误清除方式错误:
$error.clear应改为$error.Clear()(PowerShell方法调用需要括号)。 - 参数与循环变量冲突:函数参数定义的
$ComputerName被循环内的赋值覆盖,易造成逻辑混淆。 - 低效连通性测试:
Test-Connection -Count 3会发送3个数据包,改为-Count 1可大幅加快检测速度。 - 过时WMI调用:
Get-WmiObject已被弃用,推荐使用Get-CimInstance,兼容性与性能更优。 - CSV读取不规范:
Get-Content按纯文本读取CSV,若文件含表头或分隔字段会出错,建议配合空行过滤逻辑。
修复后的完整脚本
function Get-RemoteLogonStatus { [CmdletBinding()] param() # 读取CSV并过滤空行,若CSV含表头请调整为:Import-Csv -Path C:\ADComputers.csv | Select-Object -ExpandProperty 表头字段名 $computers = Get-Content C:\ADComputers.csv | Where-Object { $_ -notmatch '^\s*$' } foreach ($computer in $computers) { if (Test-Connection -ComputerName $computer -Count 1 -Quiet) { try { # 用Get-CimInstance替代过时的Get-WmiObject,直接获取登录用户信息 $loggedOnUser = Get-CimInstance -ComputerName $computer -ClassName Win32_ComputerSystem -ErrorAction Stop | Select-Object -ExpandProperty UserName if ($loggedOnUser) { Write-Output "计算机 $computer 正在使用,登录用户:$loggedOnUser" } else { Write-Output "计算机 $computer 无用户登录 - 执行重启操作。" Shutdown /r /t 0 /M \\$computer } } catch { Write-Output "计算机 $computer 连接异常:$_" # 用continue替代return,仅跳过当前异常条目,继续处理下一台计算机 continue } } else { Write-Output "计算机 $computer 离线或无法连通。" } } $error.Clear() } Get-RemoteLogonStatus
关键修复点说明
- 移除
return改用continue:避免触发异常时直接退出函数,确保循环能遍历所有条目。 - 修正属性读取逻辑:直接获取并判断
UserName属性,消除语法错误导致的异常。 - 优化检测效率:减少连通性测试的数据包数量,提升脚本执行速度。
- 替换为现代API:使用
Get-CimInstance符合PowerShell最佳实践,避免弃用警告。 - 过滤无效行:防止CSV中的空行引发无效的计算机名检测。
内容的提问来源于stack exchange,提问作者KEGS
相关产品推荐
相关产品推荐

