49 votes

PowerShell try/catch/finally

J'ai récemment écrit un script PowerShell qui fonctionne très bien - cependant, je voudrais maintenant mettre à niveau le script et ajouter une vérification / gestion des erreurs - mais j'ai été bloqué au premier obstacle, semble-t-il. Pourquoi le code suivant ne fonctionne-t-il pas ?

try {
  Remove-Item "C:\somenonexistentfolder\file.txt" -ErrorAction Stop
}

catch [System.Management.Automation.ItemNotFoundException] {
  "item not found"
}

catch {
  "any other undefined errors"
  $error[0]
}

finally {
  "Finished"
}

L'erreur est attrapée dans le deuxième bloc catch - vous pouvez voir la sortie de $error[0] . Évidemment, j'aimerais l'attraper dans le premier bloc. Qu'est-ce que je rate ?

40voto

Bruce Points 955

-ErrorAction Stop change les choses pour vous. Essayez d'ajouter ceci et voyez ce que vous obtenez :

Catch [System.Management.Automation.ActionPreferenceStopException] {
"caught a StopExecution Exception" 
$error[0]
}

0 votes

C'est assez intéressant, vu que $_.Exception est un ItemNotFoundException et non un ActionPreferencesStopException . Je parie que ce dernier conduit de RuntimeException .

0 votes

Je pense que tu as raison. J'aime ta version de l'échange. Plus en ligne avec ce que Steve essaie de faire.

8 votes

Exact, le problème ici est que c'est une erreur non terminale. Donc même si c'est une ItemNotFoundException il n'est pas réellement lancé, à moins qu'il ne soit enveloppé dans un fichier de type ActionPreferencesStopException . En tant que développeur, cela m'agace :)

31voto

Joel B Fant Points 14013

C'est très étrange.

Je suis passé par ItemNotFoundException et testé les classes multiples suivantes catch es pour voir ce que serait l'attraper :

try {
  remove-item C:\nonexistent\file.txt -erroraction stop
}
catch [System.Management.Automation.ItemNotFoundException] {
  write-host 'ItemNotFound'
}
catch [System.Management.Automation.SessionStateException] {
  write-host 'SessionState'
}
catch [System.Management.Automation.RuntimeException] {
  write-host 'RuntimeException'
}
catch [System.SystemException] {
  write-host 'SystemException'
}
catch [System.Exception] {
  write-host 'Exception'
}
catch {
  write-host 'well, darn'
}

Il s'avère que la sortie était 'RuntimeException' . J'ai également essayé avec une exception différente CommandNotFoundException :

try {
  do-nonexistent-command
}
catch [System.Management.Automation.CommandNotFoundException] {
  write-host 'CommandNotFoundException'
}
catch {
  write-host 'well, darn'
}

Ce résultat 'CommandNotFoundException' correctement.

Je me souviens vaguement avoir lu ailleurs (mais je n'ai pas pu le retrouver) des problèmes à ce sujet. Dans ces cas-là, lorsque le filtrage des exceptions ne fonctionnait pas correctement, ils capturaient la plus proche Type ils ont pu et ensuite utiliser un switch . Ce qui suit vient de se produire Exception au lieu de RuntimeException mais c'est le switch équivalent de mon premier exemple qui vérifie tous les types de base de ItemNotFoundException :

try {
  Remove-Item C:\nonexistent\file.txt -ErrorAction Stop
}
catch [System.Exception] {
  switch($_.Exception.GetType().FullName) {
    'System.Management.Automation.ItemNotFoundException' {
      write-host 'ItemNotFound'
    }
    'System.Management.Automation.SessionStateException' {
      write-host 'SessionState'
    }
    'System.Management.Automation.RuntimeException' {
      write-host 'RuntimeException'
    }
    'System.SystemException' {
      write-host 'SystemException'
    }
    'System.Exception' {
      write-host 'Exception'
    }
    default {'well, darn'}
  }
}

Cela écrit 'ItemNotFound' comme il se doit.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X