Question:
I have a script that has some functions and then multiple jobs in the very same script that use those functions. When I start a new job they don’t seem to be accessible in the [ScriptBlock]
that I have for my jobs.
Here’s a minimal example demonstrating this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# A simple test function function Test([string] $string) { Write-Output "I'm a $string" } # My test job [ScriptBlock] $test = { Test "test function" } # Start the test job Start-Job -ScriptBlock $test -Name "Test" | Out-Null # Wait for jobs to complete and print their output @(Get-Job).ForEach({ Wait-Job -Job $_ |Out-Null Receive-Job -Job $_ | Write-Host }) # Remove the completed jobs Remove-Job -State Completed |
The error that I get in PowerShell ISE is:
1 2 3 4 5 |
The term 'Test' 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: (Test:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException + PSComputerName : localhost |
Answer:
Start-Job
run jobs in separate PowerShell processes. So that, jobs do not have access to session state of calling PowerShell session. You need to define functions, which get used by jobs, in every job. An easy way to do that without duplicating the code would be using of -InitializationScript
parameter, where all common functions can be defined.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$IS = { function CommonFunction1 { 'Do something' } function CommonFunction2 { 'Do something else' } } $SB1 = { CommonFunction1 CommonFunction2 } $SB2 = { CommonFunction2 CommonFunction1 } $Job1 = Start-Job -InitializationScript $IS -ScriptBlock $SB1 $Job2 = Start-Job -InitializationScript $IS -ScriptBlock $SB2 Receive-Job $Job1,$Job2 -Wait -AutoRemoveJob |