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

PowerShell中try/catch无法捕获System.Net.NetworkInformation.Ping异常排查

问题

以下是PowerShell 5.1中使用System.Net.NetworkInformation.Ping发送带超时Ping请求的Test-Ping函数:

Function Test-Ping { # Use this instead of Test-Connection to allow increasing timeout
    Param(
        [Parameter(Mandatory=$true)][String]$ComputerName,
        [Parameter()][Int32]$Timeout = 15,
        [Parameter()][Int32]$Retries = 5
    )
    $Ping = New-Object System.Net.NetworkInformation.Ping
    while ($Retries -ne 0) {
        try {
            $PingReply = $Ping.Send($ComputerName, $Timeout * 1000)
            if ($PingReply.Status -eq 'Success') {
                return $true
            }
        }
        catch [System.Management.Automation.MethodInvocationException] { # Sometimes get error 'Exception calling "Send" with "2" argument(s): "An exception occurred during a Ping request."' - treat this as a failure
            return $false
        }
        $Retries--
    }
    $Ping.Dispose()
    return $false
}

该函数多数情况下运行正常,但偶尔第9行的$Ping.Send会抛出如下异常:

Exception calling "Send" with "2" argument(s): "An exception occurred during a Ping request."
At <script path, redacted>
+             $PingReply = $Ping.Send($ComputerName, $Timeout * 1000)
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : PingException

希望将该随机网络问题导致的异常视为Ping失败并忽略,但try/catch循环未生效。已尝试捕获System.Management.Automation.MethodInvocationException和System.Net.NetworkInformation.PingException,请问脚本存在什么问题导致异常仍被抛出?

解答

核心问题是PowerShell 5.1中,调用.NET方法抛出的非终止异常默认不会被try/catch捕获。当$Ping.Send抛出异常时,PowerShell默认将其标记为非终止错误,不会触发catch块逻辑。

要解决这个问题,需要在调用方法时添加-ErrorAction Stop参数,强制将非终止错误转为终止错误,让try/catch能够正常捕获。同时建议优先捕获底层实际抛出的System.Net.NetworkInformation.PingException,保留MethodInvocationException作为兜底。

另外原函数存在资源泄漏风险:如果在try块内通过return $true提前退出,会跳过$Ping.Dispose(),导致Ping对象未被正确释放。可以用try/finally块确保资源无论成功失败都能释放。

修改后的函数示例:

Function Test-Ping {
    Param(
        [Parameter(Mandatory=$true)][String]$ComputerName,
        [Parameter()][Int32]$Timeout = 15,
        [Parameter()][Int32]$Retries = 5
    )
    $Ping = New-Object System.Net.NetworkInformation.Ping
    try {
        while ($Retries -ne 0) {
            try {
                # 强制将非终止错误转为终止错误,确保catch能捕获
                $PingReply = $Ping.Send($ComputerName, $Timeout * 1000) -ErrorAction Stop
                if ($PingReply.Status -eq 'Success') {
                    return $true
                }
            }
            catch [System.Net.NetworkInformation.PingException] {
                # 捕获Ping底层异常,继续重试
            }
            catch [System.Management.Automation.MethodInvocationException] {
                # 捕获包装的调用异常,继续重试
            }
            $Retries--
        }
        return $false
    }
    finally {
        # 确保Ping对象始终被释放
        $Ping.Dispose()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 16:10:32