Der lockere Umgang mit Fehlern (Teil 1)

Die PowerShell bietet eine reichhaltige Auswahl an Möglichkeiten was den Umgang mit Fehlern angeht. Relativ spontan fallen mir folgende Möglichkeiten ein:

  • Das ErrorAction-Argument bzw. die $ErrorActionPreference-Variable. Die Einstellung „Continue“ ist voreingestellt, bei der Einstellung „SilentlyContinue“ werden keine Fehlermeldungen angezeigt
  • Die $?-Variable, die immer dann ein $True liefert, wenn der letzte Befehl fehlerfrei ausgeführt wurde.
  • Die Variable $LastExitcode. Sie liefert den Exitcode von externen Programmen, wie z.B. Ping oder Net.
  • Die $Error-Variable, die keine Fehlermeldung, sondern pro Fehler ein ErrorRecord-Objekt enthält (über InvocationInfo.ScriptLineNumber erhält man z.B. die Nummer des zuletzt aufgetrenen Fehlers). Über $Error[0] erhält man den zuletzt aufgetretenen Fehler.

Was schnell übersehen werden kann – einige Cmdlets bieten einen ErrorVariable-Parameter. Hier kann der Name einer Variablen angegeben werden, in der das ErrorRecord-Objekt eingetragen wird.

Und welche Cmdlets sind das? Nun, entweder man macht sich die Mühe und scrollt durch die Hilfe, oder man probiert es mit dem folgendem Befehl:

@(get-command | select-object -expandproperty parametersets | select -expandproperty parameters | where-object { $_.Name –eq „ErrorVariable“}).Length

Der @ sorgt dafür, dass aus dem Ganzen ein Array wird und damit die Length-Eigenschaft immer zur Verfügung steht, so dass sich auch feststellen lässt, ob es 0 oder 1 Elemente sind. Ist die PowerShell nicht flexibel? Microsoftsche Zauberkünste sind dies nicht. Dieses Prinzip basiert auf einer „simplen Technik“ des darunterliegenden .NET Frameworks, die Reflection heißt, und bei der sich die „Typinformationen“ eines Objekts per Befehl abfragen lassen. Wichtig ist lediglich, der selten benutzte ExpandProperty-Parameter bei Select-Object, der dafür sorgt,  dass sich die betreffend Eigenschaft „normal“ abfragen lässt.

Ein wenig seltsam ist natürlich, dass der obige Befehl zu einer 206 als Resultat führt (es gibt bekanntlich nur 129 Cmdlets bei der PowerShell, wenn keine Erweiterungen geladen wurden). Offenbar werden da einige Parameter doppelt gezählt. Bevor ich lange über die Hintergründe nachgegrübelt habe (nachzudenken ist nicht unbedingt meine Stärke; – zu mindestens nicht zu jenen Uhrzeiten, wo dieser Eintrag entstanden ist), habe ich mir ein kleines Skript gebastelt:

$AllCmds = @()

get-command | foreach-object { $Cmd=$_;

foreach ($P In $_.ParameterSets) {

foreach ($Pa In $P.Parameters) {if ($Pa.Name -eq „ErrorVariable“) {

if ([Array]::IndexOf($AllCmds,$_) -eq -1) { $AllCmds+=$_}

} } } }

$AllCmds.Length

Zwei foreach-Schleifen gehen die Auflistungen der Parameter durch. Nicht gerade kurz, aber es scheint zu funktionieren.

PS: Wenn jemand eine deutlich kürzere Lösung kennt, würde ich mich natürlich sehr über einen Hinweis freuen.

Und wem es schon immer gestört hat, dass die PowerShell kein Dir-Kommando mit einem /ad-Schalter zum Auflisten aller Verzeichnisse besitzt, definert sich eine kleine Funktion:

function Dir/Ad {

get-childitem -path . | where-object { ($_.PsIsContainer -eq $True)} }

Dass diese Function Dir/Ad heißen darf ist, nun ja, es wurde bereits erwähnt, in der Tat flexibel.

Advertisements

Kommentar verfassen

Bitte logge dich mit einer dieser Methoden ein, um deinen Kommentar zu veröffentlichen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s