red888 red888 - 3 months ago 11
PowerShell Question

Elegant way to get around scoping issues with powershell jobs

I have functions in separate files I need to run as jobs in one main file.

I need to be able to pass these functions arguments.

This is what I have:

testJobsMain.ps1:

$Functions = {
. c:\.ps\func1.ps1
. c:\.ps\func2.ps1
}

$arrOutput = @()
foreach($i in ('aaa','bbb','ccc','ddd','eee') ) {

$ExecutionBlock = {
FOO -myArg $i
FOO2 -blah 'zzzzzzz'
}

$arrOutput += Start-Job -InitializationScript $Functions `
-ScriptBlock $ExecutionBlock |
Wait-Job | Receive-Job
}

$arrOutput


func1.ps1

function FOO( $myArg ) { write-output $myArg }


func2.ps1

function FOO2( $blah ) { write-output $blah }


This is the output of testJobsMain.ps1:

PS> .\testjobsMain.ps1
zzzzzzz
zzzzzzz
zzzzzzz
zzzzzzz


It
$i
is not getting passed to the function. How can I do this?

Answer

Try it like this with GetNewClosure to capture the local $i within the loop

...
$ExecutionBlock = {
    FOO -myArg $i
    FOO2 -blah 'zzzzzzz'
}.GetNewClosure()
...

Update: Seems that closures don't work with jobs so you will have to pass it as parameter like this

$ExecutionBlock = {
    param($passedI)
    FOO -myArg $passedI
    FOO2 -blah 'zzzzzzz'
}
$arrOutput += Start-Job -InitializationScript $Functions `
    -ScriptBlock $ExecutionBlock -ArgumentList $i | 
        Wait-Job | Receive-Job

or use the using modifier (credits go to Eris) like so

...
FOO -myArg $using:i
...
Comments