locked
Difficulties timing out a function inside a foreach loop RRS feed

  • Question

  • I've written a script that has a function where if it successfully connects to the remote registry, it returns the information needed within a few seconds.  If it can't reach the remote registry, it can take up to 15 seconds before it times out.  And this needs to be ran on thousands of computers. Therefore, I want it to time out after 5 seconds on each attempt to reach a computer.

    Below is an example of the script I've written:

    $timeoutSeconds = 5
    $code = { ##sample function
            }
    
    foreach ($computer in get-content .\list.txt){
    $j = Start-Job -ScriptBlock $code
        if (Wait-Job $j -Timeout $timeoutSeconds) { Receive-Job $j }
        Remove-Job -force $j
        }
    

    The problem I see is that the $computer variable that would be passed into the function is out of scope of the start-job -scriptblock.  If I were to put the foreach loop inside the scriptblock, then I'd be losing the entire point of the timeout since I need each individual attempt to remotely reach a computer to timeout and move onto the next computer.  

    To make it work the way I have written, I need to somehow pass an out-of-scope variable into the function within the scriptblock, which to my understanding isn't possible.  Any suggestions?


    Friday, January 12, 2018 4:53 PM

Answers

  • No.  It is not out of scope.  Why would you think that.  Your code has only one scope.   Proper coding would eliminate some issues.

    $timeoutSeconds = 5
    $code = {
        dir c:\windows
    }
    
    foreach ($computer in (get-content .\list.txt)) {
        $j = Start-Job -ScriptBlock $code
        Wait-Job $j -Timeout $timeoutSeconds 
        Receive-Job $j
        Remove-Job $j -Force
    }

    Of course $computer is never used by your code.

    If you timeout a "Wait" it does not stop the job.  You have to check for a completion later a or force the job to stop.


    \_(ツ)_/



    • Edited by jrv Friday, January 12, 2018 5:55 PM
    • Marked as answer by Codyyoung37 Friday, January 12, 2018 9:06 PM
    Friday, January 12, 2018 5:46 PM
  • It was an argument in being passed into the $code section.  Here is essentially what worked:

    $timeoutSeconds = 5
    $code = {param($computer)
        write-host "$computer"
    }
    
    foreach ($computer in (get-content .\list.txt)) {
        $j = Start-Job -ScriptBlock $code -ArgumentList $computer
        Wait-Job $j -Timeout $timeoutSeconds 
        Receive-Job $j
        Remove-Job $j -Force
    }
    Obviously my script was far more complex and did a lot more than "write-host", but I'm keeping it simple on here for everyone's sanity.

    • Marked as answer by Codyyoung37 Friday, January 12, 2018 9:29 PM
    Friday, January 12, 2018 9:25 PM

All replies

  • No.  It is not out of scope.  Why would you think that.  Your code has only one scope.   Proper coding would eliminate some issues.

    $timeoutSeconds = 5
    $code = {
        dir c:\windows
    }
    
    foreach ($computer in (get-content .\list.txt)) {
        $j = Start-Job -ScriptBlock $code
        Wait-Job $j -Timeout $timeoutSeconds 
        Receive-Job $j
        Remove-Job $j -Force
    }

    Of course $computer is never used by your code.

    If you timeout a "Wait" it does not stop the job.  You have to check for a completion later a or force the job to stop.


    \_(ツ)_/



    • Edited by jrv Friday, January 12, 2018 5:55 PM
    • Marked as answer by Codyyoung37 Friday, January 12, 2018 9:06 PM
    Friday, January 12, 2018 5:46 PM
  • Yeah, it worked out.

    I noticed you typically end up answering my question jrv.  Thank you for the help.

    Our team didn't have anyone who knew PowerShell, so I took it upon myself to do a crash course and teach myself as quickly as I could despite no programming background.  So I know my code isn't always the prettiest and I don't always have the best practices, but I'm reading as many books on it as possible and constantly using Google to try to figure things out.

    I know I can be a bit frustrating perhaps, but thank you for your patience jrv

    Friday, January 12, 2018 9:06 PM
  • You still haven't explained what $computer is being used for.  It does nothing in your code.


    \_(ツ)_/

    Friday, January 12, 2018 9:11 PM
  • It was an argument in being passed into the $code section.  Here is essentially what worked:

    $timeoutSeconds = 5
    $code = {param($computer)
        write-host "$computer"
    }
    
    foreach ($computer in (get-content .\list.txt)) {
        $j = Start-Job -ScriptBlock $code -ArgumentList $computer
        Wait-Job $j -Timeout $timeoutSeconds 
        Receive-Job $j
        Remove-Job $j -Force
    }
    Obviously my script was far more complex and did a lot more than "write-host", but I'm keeping it simple on here for everyone's sanity.

    • Marked as answer by Codyyoung37 Friday, January 12, 2018 9:29 PM
    Friday, January 12, 2018 9:25 PM
  • If the wait times out you will not get all of the results even though they are accumulating.

    \_(ツ)_/

    Friday, January 12, 2018 9:36 PM