I want to use background jobs in Powershell.
How to make variables evaluated at the moment of ScriptBlock definition?
$v1 = "123"
$v2 = "asdf"
$sb = {
Write-Host "Values are: $v1, $v2"
}
$job = Start-Job -ScriptBlock $sb
$job | Wait-Job | Receive-Job
$job | Remove-Job
I get printed empty values of $v1 and $v2. How can I have them evaluated in (passed to) the scriptblock and so to the background job?
The following command starts a job object and saves the resulting job object in the $job variable. Beginning in PowerShell 6.0, you can use the background operator ( & ) at the end of a pipeline to start a background job.
The Start-Job cmdlet starts a PowerShell background job on the local computer. A PowerShell background job runs a command without interacting with the current session. When you start a background job, a job object returns immediately, even if the job takes an extended time to finish.
To run a background job on a remote computer, use the AsJob parameter that is available on many cmdlets, or use the Invoke-Command cmdlet to run a Start-Job command on the remote computer.
In the PowerShell programming language, a script block is a collection of statements or expressions that can be used as a single unit. A script block can accept arguments and return values. A script block returns the output of all the commands in the script block, either as a single object or as an array.
One way is to use the [scriptblock]::create method to create the script block from an expanadable string using local variables:
$v1 = "123"
$v2 = "asdf"
$sb = [scriptblock]::Create("Write-Host 'Values are: $v1, $v2'")
$job = Start-Job -ScriptBlock $sb
Another method is to set variables in the InitializationScript:
$Init_Script = {
$v1 = "123"
$v2 = "asdf"
}
$sb = {
Write-Host "Values are: $v1, $v2"
}
$job = Start-Job -InitializationScript $Init_Script -ScriptBlock $sb
A third option is to use the -Argumentlist parameter:
$v1 = "123"
$v2 = "asdf"
$sb = {
Write-Host "Values are: $($args[0]), $($args[1])"
}
$job = Start-Job -ScriptBlock $sb -ArgumentList $v1,$v2
The simplest solution (which requires V3 or greater) looks like this:
$v1 = "123"
$v2 = "asdf"
$sb = {
Write-Host "Values are: $using:v1, $using:v2"
}
$job = Start-Job -ScriptBlock $sb
You can think of $using as working roughly like an explicit param() block and passing -ArgumentList, only PowerShell handles that for you automatically.
I'm not at a computer to validate, but this should work:
$sb = {
param($p1,$p2)
Write-Host "Values are: $p1, $p2"
}
$job = Start-Job -ScriptBlock $sb -ArgumentList $v1,$v2
I'll double check this when I get into work.
Declare the values as parameters in the script block, then pass them in using -ArgumentList
$v1 = "123"
$v2 = "asdf"
$sb = {
param
(
$v1,
$v2
)
Write-Host "Values are: $v1, $v2"
}
$job = Start-Job -ScriptBlock $sb -ArgumentList $v1, $v2
$job | Wait-Job | Receive-Job
$job | Remove-Job
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With