Как отловить только SQL ошибок тайм-аута в PowerShell? - PullRequest
1 голос
/ 07 февраля 2020

Я пытаюсь зафиксировать только ошибки тайм-аута в скрипте для PowerShell 5.1. Ошибка выводит, что время выполнения истекло, но когда я распечатываю имя ошибки, оно возвращается с [Microsoft.SqlServer.Management.PowerShell.SqlPowerShellSqlExecutionException]. Это ловит ошибку тайм-аута, но также ловит другие ошибки. Есть ли способ указать только ошибки тайм-аута?

try
{
    $results1 = Invoke-Sqlcmd -Query $query -ConnectionString $connectionString
}
Catch [Microsoft.SqlServer.Management.PowerShell.SqlPowerShellSqlExecutionException] 
{
    Write-Output "Timeout error. Try again"
}

Ошибка без catch

Invoke-Sqlcmd: истекло время ожидания выполнения. Время ожидания истекло до завершения операции или сервер не отвечает.

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

Я не смог найти никакой документации для класса [SqlPowerShellSqlExecutionException], однако, загрузив и проверив модуль SqlServer (в частности, сборку Microsoft.SqlServer.Management.PSSnapins), я смог найти, что Класс исключения происходит непосредственно от [Exception] (поэтому нет общего типа исключения SQL, который вы могли бы catch вместо этого) и содержит ровно одно свойство с именем SqlError и типа [SqlError].

К этой документации, к сожалению, нет хорошего свойства перечисления, описывающего различные потенциальные ошибки, однако я вижу, что есть свойство Number . Я немного сбит с толку тем, что указывает последний столбец таблицы на этой странице, но похоже, что вы пишете свой блок catch следующим образом ...

Catch [Microsoft.SqlServer.Management.PowerShell.SqlPowerShellSqlExecutionException] 
{
    # Error number specified at https://docs.microsoft.com/dotnet/api/system.data.sqlclient.sqlerror.number#remarks
    if ($_.Exception.SqlError.Number -eq -2)
    {
        Write-Output "Timeout error. Try again"
    }
}

... или как это ...

Catch [Microsoft.SqlServer.Management.PowerShell.SqlPowerShellSqlExecutionException] 
{
    # Error number specified at https://docs.microsoft.com/dotnet/api/system.data.sqlclient.sqlerror.number#remarks
    if ($_.Exception.SqlError.Number -eq 258)
    {
        Write-Output "Timeout error. Try again"
    }
}

..., которое позволит вам специально определять ошибки тайм-аута. Или, возможно, вам нужно проверить оба номера ошибок. См. События и ошибки компонента Database Engine для получения длинного списка номеров ошибок, с которыми нужно сопоставляться, а также подумайте о том, чтобы записать свой блок catch, как этот, чтобы проверить, что Number вы получаете за ошибку тайм-аута. .

Catch [Microsoft.SqlServer.Management.PowerShell.SqlPowerShellSqlExecutionException] 
{
    $_.Exception.SqlError | Select-Object -Property 'Number', 'Message'
}

Существует также свойство SqlError.Message , так что в крайнем случае вы всегда можете сделать что-то подобное ...

Catch [Microsoft.SqlServer.Management.PowerShell.SqlPowerShellSqlExecutionException] 
{
    #TODO: Is $_.Exception.SqlError.Message...
    #    - ...the same string as $_.Exception.Message ?
    #    - ...a substring of     $_.Exception.Message ?
    #    - ...more specific than $_.Exception.Message ?
    if ($_.Exception.SqlError.Message -eq 'Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.')
    {
        Write-Output "Timeout error. Try again"
    }
}

By кстати, хотя Write-Output может случиться для достижения цели записи текста на консоль, если вы намереваетесь предоставить обратную связь пользователю, тогда Write-Host, Write-Information или Write-Warning были бы более подходящими командлетами для этого. См. Разница в PowerShell между Write-Host и Write-Output? .

0 голосов
/ 07 февраля 2020

Вот пример моего комментария, который может оказаться полезным.

try {
    [System.Void](New-Item -Path $LogPath -ItemType Directory -ErrorAction Stop)
} catch {
    If ($Error[0].CategoryInfo.Category -eq 'PermissionDenied' -or
        $Error[0].CategoryInfo.Reason -eq 'UnauthorizedAccessException') {
        Write-Output -InputObject "Please check that you have access to create a directory."
    } Else {
        Write-Output -InputObject "An error has occurred: $($Error[0].Exception.Message)."
    } # End If-Else.
} # End try-catch.
...