'PowerShell Use UDF in ForEach-Object -Parallel [duplicate]

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?



Solution 1:[1]

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 $_
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1