wake-up-neo.com

PowerShell try / catch / finally

Ich habe kürzlich ein PowerShell-Skript geschrieben, das hervorragend funktioniert. Ich möchte das Skript jedoch jetzt aktualisieren und einige Fehlerprüfungen/-behandlungen hinzufügen. Die erste Hürde scheint jedoch überwunden zu sein. Warum funktioniert der folgende Code nicht?

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

Der Fehler wird im zweiten catch-Block abgefangen - Sie können die Ausgabe von $error[0] Sehen. Offensichtlich möchte ich es im ersten Block fangen. Was vermisse ich?

44
steve

-ErrorAction Stop ändert die Dinge für Sie. Versuchen Sie dies hinzuzufügen und sehen Sie, was Sie bekommen:

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

Das ist sehr seltsam.

Ich habe die Basisklassen von ItemNotFoundException durchgesehen und die folgenden multiplen catches getestet, um zu sehen, was würde fängt:

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'
}

Wie sich herausstellte, war die Ausgabe 'RuntimeException'. Ich habe es auch mit einer anderen Ausnahme versucht CommandNotFoundException:

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

Dieser Ausgang 'CommandNotFoundException' richtig.

Ich erinnere mich vage, wie ich an anderer Stelle gelesen habe (obwohl ich es nicht wieder finden konnte), dass ich Probleme damit hatte. In solchen Fällen, in denen die Ausnahmefilterung nicht richtig funktioniert hat, haben sie das nächstgelegene Type abgefangen und dann ein switch verwendet. Das Folgende fängt nur Exception anstelle von RuntimeException ab, ist aber das switch Äquivalent meines ersten Beispiels, das alle Basistypen von ItemNotFoundException prüft:

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'}
  }
}

Dies schreibt 'ItemNotFound', so wie es sollte.

28
Joel B Fant