2015-12-11 1 views
1

Nous avons un script powershell qui déploie un script de base de données. Toutefois, si le script de base de données échoue, la sortie ne lance pas d'exceptions au script powershell.L'exécution de la commande n'entraîne pas d'exception de script

Voici un exemple du fichier .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" 
} 

La requête en question est en cours d'exécution sur une table inexistante. La sortie de texte indique:

[2015-12-11T14: 42: 45,1973944 + 00: 00] Msg 4902, niveau 16, état 1, serveur ABDN-DEV-PC1, Ligne 1

[2015 -12-11T14: 42: 45.2053944 + 00: 00] Impossible de trouver l'objet "xx" car il n'existe pas ou vous n'avez pas la permission s.

Réussi

J'attends la dernière ligne à lire: Échec.

Si vous exécutez la ligne sqlcmd seule et que vous la suivez avec $LastExitCode, elle crache un code de sortie différent de zéro.

> 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 

Pour diverses raisons, nous ne pouvons pas utiliser Invoke-SqlCmd, et la nécessité de rester avec Sqlcmd.exe. Comment faire en sorte que les exceptions à partir de SQLCMD sortent correctement vers le script appelant?

Répondre

3

Votre instruction -ErrorVariable DeployError ne serait déclenchée que si l'applet de commande Publish-DatabaseProject ne pouvait pas être exécutée. Comme cette fonction est principalement un wrapper autour de sqlcmd.exe, il n'y a pas d'intelligence pour faire exploser cette erreur. Nous pouvons cependant l'envelopper en utilisant la variable automatique $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 
     } 
} 

Maintenant, PowerShell attraper cette erreur du .exe, et vous pouvez utiliser -ErrorVariable.

Mise à jour

Alors, puisque vous voulez continuer à fonctionner et ne pas abandonner le navire quand enountering une erreur, nous avons besoin d'envelopper votre fonction Publish-DataBaseProject avec un bloc try{}catch{}, pour attraper l'erreur que nous générons, sans arrêt de l'exécution.

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)" 
     } 

Maintenant, nous générons bien une exception d'un CMD, barbotage à travers notre fonction, et la manipulation comme si elle était une fonction normale, tout en utilisant PowerShell native. Je crois que c'est ce que vous cherchiez à faire. Si ce n'est pas le cas, postez un aperçu de tout le script et je vous aiderai de manière plus ciblée.

+0

Il s'agit d'un niggle mineur, mais Publish-DatabaseProject est une fonction et non une cmdlet. – EBGreen

+0

Vous avez raison, j'utilise les termes de façon interchangeable parce que je suis mauvais dans mon travail. – FoxDeploy

+0

C'est une chose commune et ce n'était pas destiné à rabaisser votre réponse. Juste le signaler pour quelqu'un qui n'a pas compris qu'il y a une différence. – EBGreen