Powershell:在 Try/Catch 块中使用聚合异常的 Handle 方法

Powershell: Using the Handle method of an Aggregate Exception in a Try/Catch block

我的任务是对大约 50-60 个可能的设备执行反向 DNS 查找。在任何情况下都不会抛出聚合异常。

如果您只看控制台输出(没有红色文本),我的方法似乎有效,但仍然可以在 $Error 变量中找到异常。

到目前为止,我一直无法找到在 PowerShell 中使用 Handle 方法的示例。

我将使用从以下 link 获得的示例,但我对 C# 或 VB 不是很熟悉。我可能在转换为 PowerShell 时遇到问题。

https://msdn.microsoft.com/en-us/library/system.aggregateexception.handle(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-3

我想知道的是...我哪里出错了,或者实际上是否处理了异常?

下面的代码应该可以说明我的困惑的原因。它将创建一个由 3 个应该失败的异步反向 DNS 查找组成的任务。调用 WaitAll 应该会产生预期的聚合异常并且似乎已被处理,但仍会在 $Error 中观察到。

$Task = @('testComp1','testComp2','testComp3') | ForEach-Object {
    [pscustomobject]@{
        Computername = $_
        Task = [System.Net.DNS]::GetHostAddressesAsync($_)
    }
}

try
{
    [Void][Threading.Tasks.Task]::WaitAll($Task.Task)
}

catch [System.AggregateException]
{
    $_.Exception.Handle({
        param($ex)

        if ( $ex.GetType().Name -eq 'SocketException' ) {
            Write-Host 'Expected SocketException'
            return $true
        } else {
            return $false
        }
    })
}

$Error[0]

$Error没有关系。

Handle 方法的作用类似于 AggregateException.
中异常的过滤器 谓词返回 false 的异常将以新的 AggregateException 结束,将被抛出。

MSDN的备注。

Each invocation of the predicate returns true or false to indicate whether the Exception was handled. After all invocations, if any exceptions went unhandled, all unhandled exceptions will be put into a new AggregateException which will be thrown.

一个例子。

下面是包含 DivideByZeroExceptionIndexOutOfRangeExceptionAggregateException
请注意,第一个 catch 块显示了 2 个内部异常(#0 和 #1)。
只有 IndexOutOfRangeException 得到处理。

这会导致抛出一个新的 AggregateException,但这次只包含 DivideByZeroException。 请注意,第二个 catch 块仅显示 1 个内部异常。

try
{
    try
    {
        $divideByZeroException = (New-Object -TypeName System.DivideByZeroException)
        $indexOutOfRangeException = (New-Object -TypeName System.IndexOutOfRangeException)
        throw (New-Object -TypeName System.AggregateException -ArgumentList $divideByZeroException,$indexOutOfRangeException)
    }
    catch [System.AggregateException]
    {        
        $_.Exception.ToString() | out-host

        # System.AggregateException: One or more errors occurred. ---> System.DivideByZeroException: Attempted to divide by zero.
        # --- End of inner exception stack trace ---
        # ---> (Inner Exception #0) System.DivideByZeroException: Attempted to divide by zero.<---
        # ---> (Inner Exception #1) System.IndexOutOfRangeException: Index was outside the bounds of the array.<---

        $_.Exception.Handle({
            param($ex)

            if ($ex.GetType().Name -eq 'IndexOutOfRangeException' ) {                
                return $true
            } else {             
                return $false
            }
        })
    }
}
catch [System.AggregateException]
{    
    $_.Exception.ToString() | out-host

    # System.AggregateException: One or more errors occurred. --->         System.DivideByZeroException: Attempted to divide by zero.
    # --- End of inner exception stack trace ---
    #  at System.AggregateException.Handle(Func`2 predicate)
    #   at CallSite.Target(Closure , CallSite , Object , ScriptBlock )
    #---> (Inner Exception #0) System.DivideByZeroException: Attempted to divide by zero.<---
}