Al mirar un script Get-WebFile en PoshCode, http://poshcode.org/3226 , noté este artilugio extraño para mí:
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return
¿Cuál es la razón de esto en lugar de lo siguiente?
$URL_Format_Error = [string]"..."
Throw $URL_Format_Error
O mejor:
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
Según tengo entendido, debe usar Write-Error para errores que no terminan, y Throw para errores de terminación, por lo que me parece que no debe usar Write-Error seguido de Return. ¿Hay una diferencia?
powershell
error-handling
powershell-2.0
Bill Barry
fuente
fuente

returnno no regresar a la llamada en elprocessbloque de una función (avanzado); en su lugar, pasa al siguiente objeto de entrada en la tubería. De hecho, este es el escenario típico para generar errores sin terminación: si aún es posible procesar más objetos de entrada.Throwgenera un error de terminación de secuencia de comandos , que no es lo mismo que la declaración de errores de terminación activados, por ejemplo, porGet-Item -NoSuchParametero1 / 0.Respuestas:
Write-Errordebe usarse si desea informar al usuario de un error no crítico. Por defecto, todo lo que hace es imprimir un mensaje de error en texto rojo en la consola. No detiene una tubería o un bucle de continuar.Throwpor otro lado produce lo que se llama un error de terminación. Si usa throw, la tubería y / o el bucle actual finalizarán. De hecho, toda la ejecución se terminará a menos que use unatrapo unatry/catchestructura para manejar el error de terminación.Hay una cosa a la nota, si se establece
$ErrorActionPreferencea"Stop"y utilizaWrite-Errorse producirá un error de terminación .En el script al que se vinculó, encontramos esto:
Parece que el autor de esa función quería detener la ejecución de esa función y mostrar un mensaje de error en la pantalla, pero no quería que todo el script dejara de ejecutarse. El autor del script podría haber utilizado,
throwsin embargo, significaría que tendría que usar untry/catchal llamar a la función.returnsaldrá del ámbito actual que puede ser una función, secuencia de comandos o bloque de secuencia de comandos. Esto se ilustra mejor con el código:Salida para ambos:
Un gotcha aquí está usando
returnconForEach-Object. No interrumpirá el procesamiento como cabría esperar.Más información:
$ErrorActionPreference: about_Preference_Variablestry/catch: about_ Try_Catch_Finallytrap: about_Trapthrow: about_Throwreturn: about_Returnfuente
return.La principal diferencia entre el cmdlet Write-Error y la palabra clave throw en PowerShell es que el primero simplemente imprime algo de texto en el flujo de error estándar (stderr) , mientras que el segundo termina el procesamiento del comando o función en ejecución, que luego se maneja por PowerShell enviando información sobre el error a la consola.
Puede observar el comportamiento diferente de los dos en los ejemplos que proporcionó:
En este ejemplo, la
returnpalabra clave se ha agregado para detener explícitamente la ejecución de la secuencia de comandos después de enviar el mensaje de error a la consola. En el segundo ejemplo, por otro lado, lareturnpalabra clave no es necesaria ya que la terminación se realiza implícitamente porthrow:fuente
[System.Management.Automation.ErrorRecord], instancias, que se recopilan de forma predeterminada en la$Errorcolección automática ($Error[0]contiene el error más reciente). Incluso si solo lo usaWrite-Errorcon una cadena , esa cadena se envuelve en una[System.Management.Automation.ErrorRecord]instancia.Importante : Hay 2 tipos de errores de terminación , que desafortunadamente los temas de ayuda actuales combinan :
errores de terminación de instrucciones , según lo informado por cmdlets en ciertas situaciones no recuperables y por expresiones en las que se produce una excepción .NET / un error de tiempo de ejecución de PS; solo la declaración finaliza y la ejecución del script continúa de manera predeterminada .
guión -terminating errores (más exactamente: espacio de ejecución de terminación ), ya sea como provocadas por
Throwo por la escalada de uno de los otros tipos de error a través error-acción valor de preferencia variable / parámetroStop.A menos que sean capturados, terminan el espacio de ejecución actual (hilo); es decir, terminan no solo el script actual, sino también todos sus llamantes, si corresponde).
Para obtener una descripción completa del manejo de errores de PowerShell, consulte este problema de documentación de GitHub .
El resto de esta publicación se centra en los errores que no terminan frente a los que terminan las declaraciones .
Para complementar las respuestas útiles existentes con un enfoque en el núcleo de la pregunta: ¿Cómo elige si desea informar un error de terminación o no terminación de la declaración ?
El Informe de errores de cmdlet contiene pautas útiles; déjame intentar un resumen pragmático :
La idea general detrás de los errores que no terminan es permitir el procesamiento "tolerante a fallas" de grandes conjuntos de entrada : la falla al procesar un subconjunto de los objetos de entrada no debe (por defecto) abortar el proceso en su conjunto , potencialmente de larga duración , lo que le permite inspeccionar los errores y reprocesar solo los objetos fallidos más adelante , como se informa a través de los registros de errores recopilados en la variable automática
$Error.Informe un error NO TERMINATORIO , si su cmdlet / función avanzada:
$PSCmdlet.WriteError()para informar un error que no termina (Write-Errordesafortunadamente, no causa$?que se establezca$Falseen el alcance de la persona que llama ; consulte este problema de GitHub ).$?le indica si el comando más reciente informó al menos un error sin terminación.$?ser$Falsepuede significar que cualquier subconjunto (no vacío) de objetos de entrada no se procesó correctamente, posiblemente todo el conjunto.$ErrorActionPreferencey / o el parámetro de cmdlet común-ErrorActionpueden modificar el comportamiento de los errores sin terminación (solo) en términos de comportamiento de salida de error y si los errores sin terminación deben escalarse a los que terminan la secuencia de comandos .Informe un error de TERMINACIÓN DE DECLARACIÓN en todos los demás casos .
$PSCmdlet.ThrowTerminatingError()para generar un error de finalización de sentencia.Throwpalabra clave genera un error de terminación de script que aborta todo el script (técnicamente: el hilo actual ).try/catchcontrolador o unatrapdeclaración (que no se puede usar con errores que no terminan ), pero tenga en cuenta que incluso los errores de terminación de declaración por defecto no impiden que se ejecute el resto del script. Al igual que con los errores que no terminan ,$?refleja$Falsesi la declaración anterior activó un error de terminación de la declaración.Lamentablemente, no todos los cmdlets principales de PowerShell cumplen con estas reglas :
Si bien es poco probable que falle,
New-TemporaryFile(PSv5 +) informaría un error que no termina si falla, a pesar de no aceptar la entrada de la tubería y solo producir un objeto de salida; sin embargo, esto se ha corregido al menos desde PowerShell [Core] 7.0: vea este GitHub cuestión .Resume-JobLa ayuda afirma que pasar un tipo de trabajo no admitido (como un trabajo creado conStart-Job, que no es compatible, porqueResume-Jobsolo se aplica a los trabajos de flujo de trabajo) provoca un error de finalización, pero eso no es cierto a partir de PSv5.1.fuente
Write-Errorpermite al consumidor de la función suprimir el mensaje de error con-ErrorAction SilentlyContinue(alternativamente-ea 0). Si bienthrowrequiere untry{...} catch {..}Para usar un intento ... captura con
Write-Error:fuente
Además de la respuesta de Andy Arismendi :
Si Write-Error finaliza el proceso o no depende de la
$ErrorActionPreferenceconfiguración.Para scripts no triviales,
$ErrorActionPreference = "Stop"es una configuración recomendada para fallar rápidamente.(de http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/ )
Sin embargo, hace que las
Write-Errorllamadas terminen.Para usar Write-Error como un comando que no termina, independientemente de otras configuraciones del entorno, puede usar un parámetro común
-ErrorActioncon valorContinue:fuente
Si su lectura del código es correcta, entonces está en lo correcto. Deben usarse los errores de terminación
throw, y si se trata de tipos .NET, también es útil seguir las convenciones de excepción .NET.fuente