You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在If Else中执行操作并继续?PowerShell异常处理及$_.hostname为空问题

问题分析与解决方案

1. Catch块中$_.hostname为空的原因及解决

在catch块内,$_指向的是ErrorRecord异常对象,而非管道中遍历的CSV主机名对象,因此无法通过$_.hostname获取当前主机名。

解决方式:在循环开头将当前主机名存入独立变量,后续所有逻辑(包括catch)统一使用该变量:

$hostname | ForEach-Object {
    $currentHost = $_.hostname  # 保存当前主机到独立变量
    # 后续代码用$currentHost替代$_.hostname
}

2. If/Else结构内执行操作并继续循环

当前脚本的If/Else已经嵌套在ForEach-Object循环中,每个主机的处理都是独立的,完成当前分支的操作后会自动进入下一个主机的循环。需要注意:

  • 避免在分支内使用exit这类终止整个脚本的命令,除非明确需要停止执行。
  • 对远程连接这类耗时操作,可添加超时参数(如Test-Connection的-TimeoutSeconds),避免阻塞后续处理。

3. 正确的异常处理实践

  • 仅将可能抛出异常的命令放入try块,不要混入无关代码。
  • 必须指定-ErrorAction Stop,否则PowerShell的非终止错误不会触发catch。
  • 对New-PSSession这类可能失败的命令,也要加入异常捕获,防止脚本意外终止。

修改后的完整脚本

# 导入主机列表
$hostList = Import-Csv C:\Users\jackie.cheng\Desktop\TestComputers2.csv

# 使用泛型列表替代数组+=,提升大列表处理性能
$completedList = [System.Collections.Generic.List[PSObject]]@()
$unreachableList = [System.Collections.Generic.List[PSObject]]@()
$wmiBrokenList = [System.Collections.Generic.List[PSObject]]@()

$hostList | ForEach-Object {
    $currentHost = $_.hostname
    Write-Host "处理主机: $currentHost"

    # 测试主机连通性,-Quiet直接返回布尔值,逻辑更清晰
    if (Test-Connection -ComputerName $currentHost -Count 1 -Quiet -ErrorAction SilentlyContinue) {
        try {
            Write-Host "$currentHost 连通正常,执行远程命令..."
            # 替换为实际需要执行的远程操作,示例为WMI查询
            Invoke-Command -ComputerName $currentHost -ScriptBlock { Get-WmiObject Win32_OperatingSystem } -ErrorAction Stop

            # 尝试创建会话(按需保留,用完及时关闭)
            if ($session = New-PSSession -ComputerName $currentHost -ErrorAction Stop) {
                Write-Host "$currentHost 会话创建成功,标记为完成"
                $completedList.Add([pscustomobject]@{
                    Name   = $currentHost
                    Status = "Complete"
                })
                Remove-PSSession $session  # 释放会话资源
            }
        }
        catch {
            Write-Host "$currentHost 远程操作失败: $($_.Exception.Message)"
            $wmiBrokenList.Add([pscustomobject]@{
                Name   = $currentHost
                Status = "WMI Broken"
                Error  = $_.Exception.Message  # 可选:记录具体错误信息便于排查
            })
        }
    }
    else {
        Write-Host "$currentHost 无法连通"
        $unreachableList.Add([pscustomobject]@{
            Name  = $currentHost
            Down  = "Unreachable"
        })
    }
}

# 导出结果到CSV
$completedList | Export-Csv 'C:\Users\jackie.cheng\Desktop\SCCM Laptop Update Pushed.csv' -NoTypeInformation
$unreachableList | Export-Csv 'C:\Users\jackie.cheng\Desktop\Unreachable.csv' -NoTypeInformation
$wmiBrokenList | Export-Csv 'C:\Users\jackie.cheng\Desktop\WMIBroken.csv' -NoTypeInformation

关键优化点说明

  • 用[System.Collections.Generic.List[PSObject]]替代数组+=,避免每次扩容带来的性能损耗。
  • Test-Connection添加-Quiet参数,直接返回布尔值简化判断逻辑。
  • 将实际远程操作(原脚本误写为Test-Connection)放入try块,精准捕获远程执行异常。
  • 及时关闭PSSession,避免资源泄漏。
  • 在catch中记录具体错误信息,方便后续问题排查。

内容的提问来源于stack exchange,提问作者DrixlRey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:25:39