To complement Keith Hill’s helpful answer with a PSv3+ alternative:
The $using:
scope modifier can be used to reference the values of variables in the caller’s scope inside the script block passed to Start-Job
, as an alternative to passing arguments (by default, a script block executed as a background job does not see any of the caller’s variables or other definitions):
$Servername="Server1"
Start-Job { "Target: " + $using:ServerName } | Receive-Job -Wait -AutoRemoveJob
The above yields:
Target: Server1
Note:
-
The same technique can be used with:
-
Invoke-Command
for remote execution – see this question. -
Start-ThreadJob
, available by default in PowerShell (Core) v6+, installable on demand in Windows PowerShell. -
ForEach-Object -Parallel
, available in PowerShell (Core) v7+ only.
-
-
Note that, as with
-ArgumentList
(-Args
), it is only variable values that are being passed, not the variables themselves; that is, you cannot modify the caller’s variables.[1]
[1] However, the thread-based concurrency features – Start-ThreadJob
and ForEach-Object Parallel
– permit indirect modification, namely if the variable value at hand happens to be an instance of a (mutable) .NET reference type, such as a hashtable, in which case the object that that the variable “points to” can be modified (if it is mutable). Note that taking advantage of that requires additional, nontrivial effort to make the concurrent modifications thread-safe, such as by use of concurrent (synchronized) collections – see this answer – and/or explicit locking of individual objects – see this answer.