Control de errores

Completado

Hasta ahora, ha aprendido que la incorporación de parámetros y construcciones de control del flujo puede hacer que los scripts sean flexibles y seguros de usar. Aun así, a veces se producirán errores en los scripts. Por eso, necesita una manera de controlar los errores.

Estos son algunos de factores que se deben tener en cuenta:

  • Manera de controlar el error. A veces se obtienen errores de los que se puede recuperar y, a veces, es mejor detener el script. Es importante pensar en los tipos de errores que pueden producirse y en cómo administrarlos mejor.

  • Gravedad del error. Hay varios tipos de mensajes de error. Algunos son más bien como advertencias que indican al usuario que hay algún problema. Otros son más graves y es importante que el usuario les preste atención. El método que aplique al control de errores depende del tipo de error. Puede optar por cualquier enfoque, desde presentar un mensaje hasta aumentar el nivel de gravedad y, potencialmente, detener el script.

Errors

Un cmdlet o una función, por ejemplo, podrían generar muchos tipos de errores. Le recomendamos que escriba código para administrar los diferentes tipos de error que puedan producirse y administrarlos adecuadamente en función del tipo. Por ejemplo, supongamos que está intentando escribir en un archivo. Podría recibir varios tipos de errores, en función de cuál sea el problema. Si no tiene permiso para escribir en el archivo, es posible que reciba un tipo de error. Si el archivo no existe, recibirá otro tipo de error, y así sucesivamente.

Puede obtener dos tipos de errores al ejecutar PowerShell:

  • Error de terminación. Un error de este tipo detendrá la ejecución en la fila donde se produjo el error. Puede controlar este tipo de error mediante Try-Catch o Trap. Si no se controla el error, el script dejará de ejecutarse en ese momento y no se ejecutará ninguna instrucción.

    Nota

    La construcción Trap se encuentra fuera del ámbito de este módulo. Si le interesa, consulte Acerca de Trap.

  • Error de no terminación. Este tipo de error notificará al usuario que se ha producido un problema, pero que el script continuará. Puede actualizar este tipo de error a un error de terminación.

Administración de errores mediante Try/Catch/Finally

Puede considerar un error de terminación como un error inesperado. Estos errores son graves. Al tratar con uno, debe tener en cuenta qué tipo de error es y qué puede hacer al respecto.

Hay tres construcciones relacionadas que pueden ayudarle a administrar este tipo de error:

  • Try. El bloque Try se usará para encapsular una o varias instrucciones. El código que se quiere ejecutar se colocar entre llaves (por ejemplo, el código que escribe en un origen de datos). Un bloque Try debe tener al menos un bloque Catch o Finally. Este es su aspecto:

    Try {
       # Statement. For example, call a command.
       # Another statement. For example, assign a variable.
    }
    
  • Catch. Esta palabra clave se usará para detectar o administrar un error cuando se produce. Después, deberá inspeccionar el objeto de excepción para comprender qué tipo de error se ha producido, dónde y si el script puede recuperarse. Catch aparece inmediatamente después de Try. Si quiere, puede agregar más de un Catch —uno para cada tipo de error—. Este es un ejemplo:

    Try {
       # Do something with a file.
    } Catch [System.IO.IOException] {
       Write-Host "Something went wrong"
    }  Catch {
       # Catch all. It's not an IOException but something else.
    }
    

    El script intenta ejecutar un comando que realiza un trabajo de E/S. El primer bloque Catch detecta un tipo específico de error: [System.IO.IOException]. El último bloque Catch detecta todo lo que no sea [System.IO.IOException].

  • Finally. Las instrucciones de este bloque se ejecutarán independientemente de si se produce algún problema. Probablemente no usará mucho este bloque, pero puede ser útil para limpiar recursos, por ejemplo. Para usarlo, agréguelo como último bloque:

    Try {
       # Do something with a file.
    } Catch [System.IO.IOException] {
       Write-Host "Something went wrong"
    }  Catch {
       # Catch all. It's not an IOException but something else.
    } Finally {
       # Clean up resources.
    }
    

Inspección de errores

Hemos hablado sobre los objetos de excepción en el contexto de la detección de errores. Estos objetos se pueden usar para inspeccionar qué problema se ha producido y tomar las medidas adecuadas. Un objeto de excepción contiene lo siguiente:

  • Un mensaje. El mensaje indica en pocas palabras qué problema se ha producido.

  • El seguimiento de la pila. El seguimiento de la pila indica qué instrucciones se han ejecutado antes del error. Imagine que tiene una llamada a la función A, seguida de B y, después, de C. El script deja de responder en C. El seguimiento de la pila mostrará esta cadena de llamadas.

  • La fila incorrecta. El objeto de excepción también indica qué fila estaba ejecutando el script cuando se produjo el error. Esta información puede ayudarle a depurar el código.

¿Cómo se inspecciona un objeto de excepción? Hay una variable integrada, $_, que tiene una propiedad exception. Para obtener el mensaje de error, por ejemplo, usaría $_.exception.message. En código, tendría el aspecto siguiente:

Try {
     # Do something with a file.
   } Catch [System.IO.IOException] {
     Write-Host "Something IO went wrong: $($_.exception.message)"
   }  Catch {
     Write-Host "Something else went wrong: $($_.exception.message)"
   }

Generación de errores

En algunas situaciones, es posible que le interese producir un error:

  • Errores de no terminación. Para este tipo de error, PowerShell simplemente le notifica que se ha producido un problema, por ejemplo, mediante el cmdlet Write-Error. El script sigue ejecutándose. Es posible que ese no sea el comportamiento que quiere obtener. Para aumentar la gravedad del error, puede usar un parámetro como -ErrorAction para provocar un error que se pueda capturar con Try/Catch, de la siguiente manera:

    Try {
       Get-Content './file.txt' -ErrorAction Stop
    } Catch {
       Write-Error "File can't be found"
    }
    

    Con el parámetro -ErrorAction y el valor Stop, puede producir un error que Try/Catch puede capturar.

  • Reglas de negocio. Es posible que se encuentre con una situación en la que el código no deja de responder, pero por motivos empresariales le interese que así sea. Imagine que está saneando la entrada y que quiere comprobar si un parámetro es una ruta de acceso. Un requisito empresarial podría especificar que solo se permiten determinadas rutas de acceso o que la ruta de acceso debe tener un aspecto determinado. Si se produce un error en las comprobaciones, tiene sentido producir un error. En una situación como esta, puede usar un bloque Throw:

    Try {
       If ($Path -eq './forbidden') 
       {
         Throw "Path not allowed"
       }
       # Carry on.
    
    } Catch {
       Write-Error "$($_.exception.message)" # Path not allowed.
    }
    
    

    Nota

    En general, no use Throw para la validación de parámetros. Emplee en su lugar atributos de validación. Si no puede hacer que el código funcione con estos atributos, puede usar Throw.