powershellscopestart-jobscriptblock

Powershell start-job scope


I have a long script. i have a function for logging:

function Log ([string]$Content){
    $Date = Get-Date
    Add-Content -Path $LogPath -Value ("$Date : $Content")
}

In some point at the script i have the need to run jobs in parallel. I have a list of computer names and i need to use psexec to each one of them. this should be done as jobs to to run in parallel


        Start-Job -ScriptBlock {
        
        Log "$line Has called"
            $Program_List = gc $USERS_DB_PATH\$line.txt | select -Skip 1
            if (Test-Connection $line -Quiet) {
                    ForEach ($program in $Program_List){
                    Log "$line $program"
                    #"line $line bot is $bot pwd is $pwd"
                    psexec \\"$line" -u bla.local\"$bot" -p $pwd cmd bla
                    
                    }
            }
            else{
                  Log "Cannot Connect to $line"
            }
        
        
        }
        #Remove-Item "$USERS_DB_PATH\$line.txt"


}

I understand this is something to do with Scope but how can I make this scriptblock see the function Log and all the neccesery variables? they all come up empty


Solution

  • tl;dr

    Start-Job -ScriptBlock {
    
      # Required in Windows PowerShell only (if needed).
      # Change to the same working directory as the caller.
      Set-Location -LiteralPath ($using:PWD).ProviderPath
    
      # Recreate the Log function.
      $function:Log = "$using:function:Log"
            
      # All variable values from the *caller*'s scope must be $using: prefixed.
      Log "$using:line Has called"
      # ...        
            
    }
    

    A background job runs in an invisible PowerShell child process, i.e. a separate powershell.exe (Windows PowerShell) pwsh (PowerShell (Core) 7+) process.

    Such a child process:

    Conversely, this means that only the following commands are available by default in background jobs:


    Passing caller-state information to background jobs:

    Caveat re type fidelity:


    Preferable alternative to background jobs: thread jobs, via Start-ThreadJob:

    PowerShell (Core) 7+ comes with the ThreadJob module, which offers the Start-ThreadJob cmdlet; in Windows PowerShell you can install it on demand.

    Start-ThreadJob fully integrates with PowerShell's other job-management cmdlets, but uses threads (i.e. in-process concurrency) rather than child processes, which implies:

    Also, the caller's working directory is inherited.

    The need for $using: / -ArgumentList equally applies.

    This answer provides an overview of ForEach-Object -Parallel and compares and contrasts Start-Job and Start-ThreadJob.