rainu
rainu

Reputation: 763

Execute function in parallel throws error in powershell

I was following the example given in post

to call a simple function in parallel. I am getting the error but unable to figure out why.

Below is the code block.

function run-thescript 
{
  param (
        $Parameter1,
        $Parameter2
    )
#Write-Host 'inside the outer function'
Write-Output "the first parameter is $Parameter1 and second is $Parameter2"
}

$cmd = {
  param($a, $b)
  Write-Host $a $b
  run-thescript -Parameter1 $a -Parameter2 $b
}

Start-Job -ScriptBlock $cmd -ArgumentList @('input1','input2')

Error thrown after running

Get-Job | % { Receive-Job $_.Id; Remove-Job $_.Id }

is

The term 'run-thescript' is not recognized as the name of a cmdlet, function, 
script file, or operable program. Check the spelling of the name, or if a path 
was included, verify that the path is correct and try again.
    + CategoryInfo          : ObjectNotFound: (run-thescript:String) [], Comma 
   ndNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    + PSComputerName        : localhost

Upvotes: 1

Views: 372

Answers (1)

SteloNLD
SteloNLD

Reputation: 601

The issue is that the Job scope (just like a new PowerShell window) does not know about the functions but, there are two ways to do this in my opinion, the functions need to be delcared after the param statement so something like $functions+$cmd will not work with the provided example, as a workaround you could use $using:variable instead of Param() to transport arguments to the Job scope or inject the functions themself as an argument.

examples using $using: below:

# -----------------------------------------------------------
# *                                                 Functions
# -----------------------------------------------------------

# -----------------------------------------------------------
# *                                             run-thescript

function run-thescript 
{
    param (
        $Parameter1,
        $Parameter2
    )

    Write-Output "the first parameter is $Parameter1 and second is $Parameter2"
}

# -----------------------------------------------------------
# *                                                 Execution
# -----------------------------------------------------------

# -----------------------------------------------------------
# *                                         Capture functions

# specify the functions here
$Functions = @(
    'run-thescript'
    #"some-function"
    #"other-function"
)

# This will look for the specified functions and store them in the $functions variable.
$Functions = $Functions | ForEach-Object {
    Write-Verbose -Message "Processing $($PSItem)"
    (Get-Item -Path "Function:\$($PSItem)").ScriptBlock.StartPosition.Content
}

# -----------------------------------------------------------
# *                                         Parse and Execute

$a = 'input1'
$b = 'input2'

$ScriptBlock = {
    $a = $using:a
    $b = $using:b
    Write-Host $a $b
    run-thescript -Parameter1 $a -Parameter2 $b
}

Start-Job -ScriptBlock ([Scriptblock]::Create($Functions + $ScriptBlock))

Upvotes: 1

Related Questions