Powershell: использование метода Handle для Aggregate Exception в блоке Try / Catch - PullRequest
0 голосов
/ 10 июня 2018

У меня есть задача, которая выполняет обратный поиск DNS около 50-60 возможных устройств.Ни в коем случае не будет генерироваться агрегированное исключение.

То, что у меня, похоже, работает, если вы просто выходите из консоли (без красного текста), но исключение все еще можно найти в переменной $ Error,

Мне пока не удалось найти пример использования метода Handle в PowerShell.

Я ухожу из примеров, полученных по следующей ссылке, но я не оченьзнакомы с 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]

1 Ответ

0 голосов
/ 11 июня 2018

Нет никакой связи с $Error.

Метод Handle действует как фильтр для исключений в пределах AggregateException.
Исключения, для которых предикат вернул false, конецв новом AggregateException, который будет брошен.

См. примечания к MSDN .

Каждый вызов предиката возвращает true или false, чтобы указатьбыло ли обработано исключение.После всех вызовов, если какие-либо исключения остались необработанными, все необработанные исключения будут помещены в новое исключение AggregateException, которое будет выброшено.

Пример.

Здесьниже AggregateException, содержащего DivideByZeroException и выбрасывается IndexOutOfRangeException.
Обратите внимание, что первый блок 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.<---
}
...