2

I have some dificulties with using an User Define Function inside the ForEach-Object when the Parallel is active:

function Add([Int]$number) {
    Write-Output "Run for $number"
}

1..4 | ForEach-Object -Parallel {
    Add -number $_
}

I get an error message:

The term 'Add' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

I believe it is a common proactivity use an UDF inside foreach loop. Do you have any workaround for that? The $using: is applicable only for variable, not function, right?

1
  • 2
    As for $using: only working with variables: indeed, although you can - in principle - use namespace variable notation to get a function's body, as a script block: $using:function:Add. However, while that works with Start-Job and Start-ThreadJob, it is explicitly prevent with ForEach-Object -Parallel (and, based on the rationale for that, should probably be prevented in Start-ThreadJob too). See the linked duplicate for details. Commented Feb 25, 2022 at 16:28

1 Answer 1

3

You could either define the function in the scope of the parallel block (Runsapce):

1..4 | ForEach-Object -Parallel {
    function Add([Int]$number) {
        Write-Output "Run for $number"
    }
    
    Add -number $_
}

Or store the definition of your function and then pass it to the scope of your parallel block and dot source it:

function Add([Int]$number) {
    Write-Output "Run for $number"
}

$def = "function Add { ${function:Add} }"

1..4 | ForEach-Object -Parallel {
    . ([scriptblock]::Create($using:def))
    Add -number $_
}

Linked helpful answer from mklement0 shows a much more cleaner alternative to define the function in the parallel scope. Definitely recommend this method, easier to read and understand:

function Add([Int]$number) {
    Write-Output "Run for $number"
}

$def = ${function:Add}.ToString()

1..4 | ForEach-Object -Parallel {
    $function:Add = $using:Def
    Add -number $_
}
Sign up to request clarification or add additional context in comments.

3 Comments

@mklement0 actually a lot cleaner the approach on the linked answer, wasn't aware of it. Thanks
👍 Including the function definition directly in the -Parallel script block is a pragmatic solution, though not always a (clean) option.
I have always used this method and always wondered if there was something cleaner, guess I learnt something new today, as per usual with your answers :P @mklement0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.