Search code examples
t-sqlpowershellerror-handlingsqlcmdexit-code

Capturing in PowerShell different sqlcmd exitcode for connectivity/data issues


I am calling sqlcmd from PowerShell to execute a T-SQL script. Currently I am using ":On Error exit" to exit the script if there is an error caused by the data used violating a constraint etc. This is handled by PowerShell detecting the $SqlcmdProcess.ExitCode of 1.

However, if there is a connectivity issue with the database, sqlcmd also gives an ExitCode of 1. Is there a way to set the :On Error ExitCode to something other than 1? I'm aware of using something like :Exit(SELECT 2) to do this, but I'd rather still use :On Error so I don't have to rewrite the script.


Solution

  • You could use the exit keyword in Powershell. Here's an example

    Create a script called sqlcmdexit.ps1, with something like the following:

    $result = sqlcmd -S"missing" -d master -Q "select @@servername"
    if ($result[1] -like "*Error Locating Server/Instance Specified*" -or $result[1] -like "*Could not open a connection to SQL Server*") {
        exit 99
    }
    

    Call script and observe exist code:

    C:\Users\Public\bin>.\sqlcmdExit.ps1
    Sqlcmd: Error: Microsoft SQL Server Native Client 10.0 : A network-related or instance-specific error has occurred while
     establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and i
    f SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..
    Sqlcmd: Error: Microsoft SQL Server Native Client 10.0 : Login timeout expired.
    
    C:\Users\Public\bin>$LASTEXITCODE
    99
    

    I'm not aware of any way to set default ExitCode. Using start-process you could something similar:

    $tempFile = [io.path]::GetTempFileName()
    $exitCode = (Start-Process -FilePath "sqlcmd.exe" -ArgumentList @"
    -S"missing" -d master -Q "select @@servername"
    "@ -Wait -NoNewWindow -RedirectStandardOutput $tempFile -Passthru).ExitCode
    
    if ($exitCode -eq 1) {
        $result = get-content $tempfile
        if ($result[1] -like "*Error Locating Server/Instance Specified*" -or $result[1] -like "*Could not open a connection to SQL Server*") {
            remove-item $tempFile
            Exit 99
        }
    }
    else {
        remove-item $tempfile
        Exit $exitCode
    }