Share via


Difficulties timing out a function inside a foreach loop

Question

Friday, January 12, 2018 4:53 PM

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?

All replies (5)

Friday, January 12, 2018 5:46 PM ✅Answered

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.

\(ツ)_/


Friday, January 12, 2018 9:25 PM ✅Answered

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.


Friday, January 12, 2018 9:06 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:11 PM

You still haven't explained what $computer is being used for.  It does nothing in your code.

\(ツ)_/


Friday, January 12, 2018 9:36 PM

If the wait times out you will not get all of the results even though they are accumulating.

\(ツ)_/