1

我试图在 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:执行超时已过期。在操作完成之前超时时间已过或服务器没有响应。

4

2 回答 2

0

我无法找到[SqlPowerShellSqlExecutionException]该类的任何文档,但是,通过下载和检查SqlServer模块(特别是Microsoft.SqlServer.Management.PSSnapins程序集),我能够发现异常类直接派生自[Exception](因此没有通用的 SQL 异常类型可以catch代替) 并且只包含一个名为SqlErrorand 类型的属性[SqlError]

不幸的是,看看那个文档,没有一个很好的枚举属性来描述各种潜在的错误,但是我确实看到有一个Numberproperty。我有点困惑该页面上表格的最后一列是什么意思,但如果你这样写你的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"
    }
}

...这将允许您专门针对超时错误。或者您可能需要检查这两个错误号。有关要匹配的冗长错误编号列表,请参阅数据库引擎事件和错误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"
    }
}

顺便说一句,虽然Write-Output可能会碰巧实现将文本写入控制台的目标,但如果您的意图是向用户提供反馈,那么Write-HostWrite-Information或者Write-Warning将是更合适的 cmdlet。查看Write-Host 和 Write-Output 之间的 PowerShell 区别?.

于 2020-02-06T23:06:59.240 回答
0

这是我上述评论的一个示例,可能会有所帮助。

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.
于 2020-02-06T22:12:16.503 回答