Search notes:

PowerShell: call operator (&)

The call operator executes code in child scope. Thus, any modification that are made to functions, aliases, variables etc. have no effect to the calling scope.
This is in contrast to the dot sourcing operator which executes code in the current context and thus allows modifications of it.
If an ampersand is used at the end of a pipeline, the ampersand does not act as the call operator, instead the pipeline will be run as a PowerShell job.

Run a command stored in a string

$printSomething = 'write-host'
& $printSomething 'hello World'
Github repository about-PowerShell, path: /language/operator/call/printSomething.ps1

Script block

& also executes the content of a script block.
$scriptBlock = { write-host 'Hello world' }

& $scriptBlock
Github repository about-PowerShell, path: /language/operator/call/script-block/Hello-world.ps1
With the param statement, it's possible to pass values to the script block:
$sb = {
  param($param_1, $param_2)

  write-output "param_1 = $param_1"
  write-output "param_2 = $param_2"
}

& $sb -param_1 42 -param_2 'hello world'
Github repository about-PowerShell, path: /language/operator/call/script-block/param.ps1
A script block can reference variables of the scope that invoked the scriptblock. The value of the variable will be that of its value at the time the script block was invoked, not at the time the script block was created.
This example also demonstrates that modifying a variable's value has no effect in the calling scope:
$num = 99

$scriptBlock = {

  write-host "num = $num"
  write-host "txt = $txt"

  $txt = 'changed'
  $num =  0

}

$num = 42
$txt ='Hello world'

& $scriptBlock

echo "txt (after running scriptBlock): $txt"
echo "num (after running scriptBlock): $num"

#
# Script output is:
#
#  num = 42
#  txt = Hello world
#  txt (after running scriptBlock): Hello world
#  num (after running scriptBlock): 42
Github repository about-PowerShell, path: /language/operator/call/script-block/variables.ps1

Execute an executable

The call operator can also be used to execute an exe. Parts of the path can be stored in a variable:
PS C:\> & $home\bin\foo.exe

No new process is spawned

Although a called script runs in its own scope, PowerShell does not create a new process to run the script (as might be expected from other (Unix) shells).
This is demonstrated with the following two scriptlets:

call-script.ps1

call-script.ps just prints the process identifier ($PID) and then calls the-script.ps.
write-host "My PID is $PID"

& ./the-script.ps1

the-script.ps1

This is the script that is called by the script above:
write-host "the-script.ps1 runs with PID = $PID"

Output

The output demonstrates that both script's process identifiers are equal, so no new process was created:
My PID is 161944
the-script.ps1 runs with PID = 161944

Executing «dynamic» commands

The call operator does not try to parse the argument that is given to it
$a = 12
$b = 21
$cmd = "write-host ($a+$b)"
& $cmd
The sequence above results in the error message The term 'write-host (12+21)' is not recognized as a name of a cmdlet, function, script file, or executable program..
In order to execute such dynamic commands, invoke-expression can be used:
invoke-expression $cmd

See also

&& is a pipeline chain operator.
operators

Index