How to call a powershell function within the script from Start-Job? How to call a powershell function within the script from Start-Job? powershell powershell

How to call a powershell function within the script from Start-Job?


An easy way to include local functions in a background job:

$init=[scriptblock]::create(@"function DoWork {$function:DoWork}"@)Start-Job -Name "DoActualWork" $ScriptBlock -ArgumentList $array -InitializationScript $init | Out-Null


Background jobs are run in a seperate process, so the jobs you create with Start-Job can not interact with functions unless you include them in the $scriptblock.

Even if you included the function in the $scripblock, Write-Host would not output it's content to the console until you used Get-Job | Receive-Job to recieve the jobs result.

EDIT The problem is that your DisplayMessage function is in a local script-scope while your eventhandler runs in a different parent scope(like global which is the session scope), so it can't find your function. If you create the function in the global scope and call it from the global scope, it will work.

I've modified your script to do this now. I've also modified to scriptblock and unregistered the events when the script is done so you won't get 10x messages when you run the script multiple times :-)

Untitled1.ps1

function DoWork{  $event = Register-EngineEvent -SourceIdentifier NewMessage -Action {      global:DisplayMessage $event.MessageData  }  $scriptBlock =  {    Register-EngineEvent -SourceIdentifier NewMessage -Forward    $message = "Starting work $args"    $null = New-Event -SourceIdentifier NewMessage -MessageData $message    ### DO SOME WORK HERE ###    $message = "Ending work $args"    $null = New-Event -SourceIdentifier NewMessage -MessageData $message    Unregister-Event -SourceIdentifier NewMessage  }  DisplayMessage("Processing Starts")  $array = @(1,2,3)  foreach ($a in $array)  {      Start-Job -Name "DoActualWork" $ScriptBlock -ArgumentList $a | Out-Null  }  #$jobs = Get-Job -Name "DoActualWork"  While (Get-Job -Name "DoActualWork" | where { $_.State -eq "Running" } )  {      Start-Sleep 1  }  DisplayMessage("Processing Ends")  #Get-Job -Name "DoActualWork" | Receive-Job}function global:DisplayMessage([string]$message){    Write-Host $message -ForegroundColor Red}DoWorkGet-EventSubscriber | Unregister-Event

Test

PS > .\Untitled1.ps1Processing StartsStarting work 1Starting work 2Ending work 1Ending work 2Starting work 3Ending work 3Processing Ends


I got it to work as follows;

function CreateTable {    $table = "" | select ServerName, ExitCode, ProcessID, StartMode, State, Status, Comment    $table}$init=[scriptblock]::create(@"  function CreateTable {$function:createtable}"@)