2011-07-21 18 views
41

Recientemente escribí un script de Powershell que funciona genial. Sin embargo, me gustaría actualizar ahora el script y agregar algunas comprobaciones/manejo de errores. Pero me he quedado perplejo ante el primer obstáculo que parece . ¿Por qué no funcionará el siguiente código?Powershell try/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" 
} 

El error se ve atrapado en el segundo bloque catch - Se puede ver la salida de $error[0]. Obviamente me gustaría atraparlo en el primer bloque. ¿Qué me estoy perdiendo? Gracias

Respuesta

35

-ErrorAction Stop está cambiando cosas para usted. Intente agregar esto y vea lo que obtiene:

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

Eso es bastante interesante, considerando '$ _. Exception' es una' ItemNotFoundException' y no una 'ActionPreferencesStopException'. Apuesto a que este último conduce desde 'RuntimeException'. –

+0

Creo que tienes razón. Me gusta tu versión de interruptor. Más en línea con lo que steve está tratando de hacer. – Bruce

+7

Correcto, el problema aquí es que es un error que no termina. Entonces, aunque es una 'ItemNotFoundException', en realidad no se lanza a menos que esté envuelto en una 'ActionPreferencesStopException'. Como desarrollador, esto me molesta. :) – JasonMArcher

23

Eso es muy extraño.

Fui a través de clases base ItemNotFoundException 's y se probaron los siguientes múltiples catch es para ver lo que haría capturas que:

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

Como resultado, la salida era 'RuntimeException'. También he probado con una excepción diferente CommandNotFoundException:

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

que la producción 'CommandNotFoundException' correctamente.

I vagamente recuerdo haber leído en otro lugar (aunque no pude encontrarlo de nuevo) de problemas con esto. En los casos en que el filtrado de excepciones no funcionara correctamente, capturarían el Type más cercano que pudieran y luego usarían un switch. El siguiente justo atrapa Exception en lugar de RuntimeException, pero es el equivalente de switch mi primer ejemplo que comprueba todos los tipos de bases 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'} 
    } 
} 

Esto escribe 'ItemNotFound', como debe ser.

+0

Consulte la cadena de comentarios en la respuesta de Bruce. – JasonMArcher