2011-07-21 10 views
41

Niedawno napisałem skrypt Powershell, który działa świetnie - chciałbym jednak zaktualizować skrypt i dodać błąd sprawdzania/obsługi - ale byłem zaskoczony pierwszą przeszkodą . Dlaczego poniższy kod nie działa?Powershell/catch/finally

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

Błąd jest złowionych w drugim bloku catch - Można zobaczyć wyjście z $error[0]. Oczywiście chciałbym go złapać w pierwszym bloku - Czego mi brakuje? Dzięki

Odpowiedz

35

-ErrorAction Stop zmienia dla ciebie rzeczy. Spróbuj dodać to i zobacz, co otrzymasz:

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

To całkiem interesujące, biorąc pod uwagę '$ _. Exception' to' ItemNotFoundException', a nie 'ActionPreferencesStopException'. Założę się o te ostatnie dyski z 'RuntimeException'. –

+0

Myślę, że masz rację. Podoba mi się twoja wersja przełącznika. Bardziej zgodnie z tym, co próbuje steve. – Bruce

+7

W porządku, problem polega na tym, że jest to błąd nie kończący się. Więc nawet jeśli jest to 'ItemNotFoundException', to nie jest faktycznie otrzymywane, dopóki nie zostanie zapakowane w' ActionPreferencesStopException'. Jako programista to mnie denerwuje. :) – JasonMArcher

23

To bardzo dziwne.

przeszedłem klas bazowych ItemNotFoundException „s i przetestowała następujące wielu catch es zobaczyć to co by haczyk:

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

Jak się okazuje, wyjście było 'RuntimeException'. Ja też próbowałem z innym wyjątkiem CommandNotFoundException:

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

To wyjście 'CommandNotFoundException' poprawnie.

Niejasno pamiętam, że czytałem gdzie indziej (choć nie mogłem go znaleźć) problemy z tym związane. W przypadkach, w których filtrowanie wyjątków nie działało poprawnie, przechwytują one najbliższe Type mogą, a następnie korzystają z switch. Następujący po prostu łapie Exception zamiast RuntimeException, ale jest switch odpowiednik mój pierwszy przykład, który sprawdza wszystkie typy bazowe 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'} 
    } 
} 

To pisze 'ItemNotFound', jak powinno.

+0

Zobacz wątek komentarza w odpowiedzi Bruce'a. – JasonMArcher