web-dev-qa-db-fra.com

PowerShell try / catch / enfin

J'ai récemment écrit un script PowerShell qui fonctionne très bien - cependant, j'aimerais maintenant mettre à niveau le script et ajouter une vérification/gestion des erreurs - mais j'ai été bloqué au premier obstacle, il semble. 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 intercepté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?

44
steve

-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]
}
36
Bruce

C'est très étrange.

J'ai parcouru les classes de base de ItemNotFoundException et testé les multiples catches suivants pour voir ce que le ferait le rattraperait:

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'. Je l'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'
}

Cette sortie 'CommandNotFoundException' correctement.

Je me souviens vaguement d'avoir lu ailleurs (bien que je ne puisse pas le retrouver) des problèmes avec cela. Dans de tels cas où le filtrage d'exceptions ne fonctionnait pas correctement, ils attraperaient le Type le plus proche qu'ils pourraient, puis utiliseraient un switch. Ce qui suit ne capture que Exception au lieu de RuntimeException, mais est l'équivalent switch 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.

28
Joel B Fant