Saltar al contenido

PowerShell Probar/Capturar y reintentar

Te recomendamos que pruebes esta respuesta en un ambiente controlado antes de enviarlo a producción, saludos.

Solución:

Si con frecuencia necesita un código que vuelva a intentar una acción varias veces, puede envolver su bucle try..catch en una función y pase el comando en un scriptblock:

function Retry-Command 
    [CmdletBinding()]
    Param(
        [Parameter(Position=0, Mandatory=$true)]
        [scriptblock]$ScriptBlock,

        [Parameter(Position=1, Mandatory=$false)]
        [int]$Maximum = 5,

        [Parameter(Position=2, Mandatory=$false)]
        [int]$Delay = 100
    )

    Begin 
        $cnt = 0
    

    Process 
        do 
            $cnt++
            try 
                $ScriptBlock.Invoke()
                return
             catch 
                Write-Error $_.Exception.InnerException.Message -ErrorAction Continue
                Start-Sleep -Milliseconds $Delay
            
         while ($cnt -lt $Maximum)

        # Throw an error after $Maximum unsuccessful invocations. Doesn't need
        # a condition, since the function returns upon successful invocation.
        throw 'Execution failed.'
    

Invoque la función de esta manera (el valor predeterminado es 5 reintentos):

Retry-Command -ScriptBlock 
    # do something

o así (si necesita una cantidad diferente de reintentos en algunos casos):

Retry-Command -ScriptBlock 
    # do something
 -Maximum 10

La función podría mejorarse aún más, por ejemplo, haciendo la terminación del script después de $Maximum intentos fallidos configurables con otro parámetro, de modo que puede tener acciones que harán que el script se detenga cuando fallan, así como acciones cuyas fallas pueden ignorarse.

Adapté la respuesta de @Victor y agregué:

  • parámetro para reintentos
  • ErrorAction establecido y restaurado (o de lo contrario, las excepciones no quedan atrapadas)
  • retraso de retroceso exponencial (sé que el OP no pidió esto, pero lo uso)
  • se deshizo de las advertencias de VSCode (es decir, reemplazó sleep con Start-Sleep)
# [Solution with passing a delegate into a function instead of script block](https://stackoverflow.com/a/47712807/)
function Retry()

    param(
        [Parameter(Mandatory=$true)][Action]$action,
        [Parameter(Mandatory=$false)][int]$maxAttempts = 3
    )

    $attempts=1    
    $ErrorActionPreferenceToRestore = $ErrorActionPreference
    $ErrorActionPreference = "Stop"

    do
    
        try
        
            $action.Invoke();
            break;
        
        catch [Exception]
        
            Write-Host $_.Exception.Message
        

        # exponential backoff delay
        $attempts++
        if ($attempts -le $maxAttempts) 
            $retryDelaySeconds = [math]::Pow(2, $attempts)
            $retryDelaySeconds = $retryDelaySeconds - 1  # Exponential Backoff Max == (2^n)-1
            Write-Host("Action failed. Waiting " + $retryDelaySeconds + " seconds before attempt " + $attempts + " of " + $maxAttempts + ".")
            Start-Sleep $retryDelaySeconds 
        
        else 
            $ErrorActionPreference = $ErrorActionPreferenceToRestore
            Write-Error $_.Exception.Message
        
     while ($attempts -le $maxAttempts)
    $ErrorActionPreference = $ErrorActionPreferenceToRestore


# function MyFunction($inputArg)
# 
#     Throw $inputArg
# 

# #Example of a call:
# Retry(MyFunction "Oh no! It happened again!")
# Retry MyFunction "Oh no! It happened again!" -maxAttempts 10

Solución con pasar un delegado a una función en lugar de un bloque de script:

function Retry([Action]$action)

    $attempts=3    
    $sleepInSeconds=5
    do
    
        try
        
            $action.Invoke();
            break;
        
        catch [Exception]
        
            Write-Host $_.Exception.Message
                    
        $attempts--
        if ($attempts -gt 0)  sleep $sleepInSeconds 
     while ($attempts -gt 0)    


function MyFunction($inputArg)

    Throw $inputArg


#Example of a call:
Retry(MyFunction "Oh no! It happend again!")

Te mostramos reseñas y calificaciones

Si para ti ha sido de ayuda nuestro post, agradeceríamos que lo compartas con más seniors así contrubuyes a difundir esta información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *