执行命令不会导致脚本异常

时间:2015-12-11 14:46:22

标签: powershell error-handling sqlcmd

我们有一个部署数据库脚本的powershell脚本。但是,如果数据库脚本失败,则输出不会向PowerShell脚本抛出异常。

以下是.ps1文件的示例:

function Publish-DatabaseProject 
{
    sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
}

function Add-Timestamp {
    process {
        if ($_.GetType() -eq [string]) {
            "[$(Get-Date -Format o)] $_"
        } else {
            $_
        }
    }
}

function Write-LogFile {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)] [string] $Path,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [object[]] $InputObject
    )

    begin {
        $root = Split-Path -Path $Path -Parent
        if ($root -and !(Test-Path -Path $root)) { New-Item -Path $root -Type Directory 
                              | Out-Null }
    }

    process {
        $InputObject |
            Add-Timestamp |
            Tee-Object -File $Path -Append
    }
}

Publish-DatabaseProject -ErrorVariable DeployError 2>&1 |
    Write-LogFile -Path "C:\output.log"

if ($DeployError -and $DeployError.Count -ne 0) 
{
    Write-Output "Failed"
} else 
{
    Write-Output "Succeeded"
}

有问题的查询是针对不存在的表执行的。文本输出显示:

  

[2015-12-11T14:42:45.1973944 + 00:00] Msg 4902,Level 16,State 1,Server ABDN-DEV-PC1,Line 1

     

[2015-12-11T14:42:45.2053944 + 00:00]无法找到对象" xx"因为它不存在或您没有权限   第

     

成功

我期待最后一行阅读:失败。

如果您自己运行sqlcmd行,并使用$LastExitCode进行跟踪,则会吐出非零退出代码。

> sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
Msg 4902, Level 16, State 1, Server ABDN-DEV-PC1, Line 1
Cannot find the object "xx" because it does not exist or you do not have permissions.
> $LastExitCode
1

由于各种原因,我们无法使用Invoke-SqlCmd,并且需要坚持使用SQLCMD.exe。

我们如何才能将SQLCMD内的异常正确地映射到调用脚本?

1 个答案:

答案 0 :(得分:3)

如果-ErrorVariable DeployError cmdlet本身无法执行,则只会触发Publish-DatabaseProject语句。由于该函数主要是sqlcmd.exe的包装器,因此没有任何智能来冒泡这个错误。我们可以使用$LastExitCode自动变量来包装它。

function Publish-DatabaseProject 
{
    sqlcmd -S . -b -v DatabaseName=Integration -q "alter table xx add test Varchar(10)"
    if ($LastExitCode -ne 0)
       {
    Write-error $LastExitCode

    throw $LastExitCode
      }
}

现在,PowerShell将从.exe中捕获此错误,您可以使用-ErrorVariable

<强>更新

因此,既然您想要在遇到错误时继续运行而不是放弃发货,我们需要用Publish-DataBaseProject块包裹您的try{}catch{}函数,以捕获我们正在生成的错误,不停止执行。

try {Publish-DatabaseProject -ErrorAction STOP -ErrorVariable DeployError 2>&1 |
    Write-LogFile -Path "C:\output.log" }


 catch{
      Write-Output "Current job $($_), failed"
      Write-Output "Exception $($Error.ExceptionID)"
      }

现在我们正在从CMD中正确生成异常,通过我们的函数对其进行冒泡,并将其作为正常函数进行处理,所有这些都使用Native PowerShell。我相信这就是你想要做的。如果没有,请发布整个剧本的要点,我会以更有针对性的方式帮助您。