Search code examples
powershellfunctionerror-handlingretry-logicscriptblock

How can I print script block content in PowerShell


Hi guys, I want to create a function that will be checking execution of selected commands and in case of catched failure retry 3 times and display the command name with the retry message. I placed a test command "Test Connection" between the function brackets to be evaluted, retry seems to be working, however I can not get the command name to be printed. I tried with "$($MyInvocation.MyCommand.ScriptBlock)", but it prints out the whole function intead of that executed line that I'm checking. Can anyone please advice here? Thanks a lot in advance

function Execute-WithRetry([ScriptBlock]$command) {

    $Stoploop = $false
    $count = 0
 
    do {
        try {
            & $command
            Write-Host "Download completed"
            $Stoploop = $true
        }
        catch {
            if ($count -eq 3) {
               
                Write-Host "Could not download after 3 retries."
                $Stoploop = $true
            }
            else {
                Write-Host "Could not download the files retrying in 5 seconds..."
                Write-Host "Executing: $($MyInvocation.MyCommand.ScriptBlock)"
                Start-Sleep -Seconds 5
            }
        }
        $count++
    }
    While  ($Stoploop -eq $false)
    pause

    }


Execute-WithRetry {
  Test-Connection -ComputerName 192.10.129.15 -ErrorAction Stop
}

Solution

  • As mentioned in the comments, if you want just the "offending" line from the script block, grab the invocation info from the error record inside the catch block (as opposed to $MyInvocation) and use the Line property to get the line on which the statement that failed starts:

    function Invoke-Retry {
      param([scriptblock]$Command)
    
      $stop = $false
      $count = 0
    
      $ErrorActionPreference = 'Stop'
    
      do {
        try {
          &$Command
    
          Write-Host "Download completed"
          $stop = $true
        }
        catch {
          if ($count -ge 3) {
            Write-Host "Could not download after 3 retries."
            $stop = $true
          }
          else {
            Write-Host "Could not download the files, retrying in 5 seconds"
            Write-Host "Error occurred while executing: `n>> $($_.InvocationInfo.Line)" -ForegroundColor Red
            Start-Sleep -Seconds 5
          }
        }
        $count++
      } while (-not $stop)
      pause
    }
    

    Which should give you the actual line from the script block:

    PS ~> Invoke-Retry {
      Test-Connection -ComputerName doesntexist
    }
    Could not download the files retrying in 5 seconds
    Error occurred while executing:
    >>   Test-Connection -ComputerName doesntexist
    
    Could not download the files retrying in 5 seconds
    Error occurred while executing:
    >>   Test-Connection -ComputerName doesntexist
    
    Could not download the files retrying in 5 seconds
    Error occurred while executing:
    >>   Test-Connection -ComputerName doesntexist
    
    Could not download after 3 retries.
    Press Enter to continue...:
    

    Note: starting with version 7.4, the invocation info class also exposes the full extent of any multiline statements via the Statement property