How to Assign Variable as Expression or Function then Invoke It
Problem
In any programming language, typically there is a feature called anonymous function where it allows us to store expression or function into a variable. The function, then, can be invoked through the variable.
For example, in JavaScript we can create anonymous function as follows:
const x = function (a, b) {return a + b};
let z = x(4, 3);
Similarly in PowerShell, we can also create anonymous function through a feature called Script Block
.
Solution
A Script Block
is a group of statements or expressions that can be used together as a single unit. The statements or expressions in Script Block must be enclosed with braces {}
. The script block can receive parameters and return values.
{ <statements/expressions> }
Using Script Block
For example, we want to put Get-Random
cmdlet into Script Block, then invoke the function through the assigned variable.
$func = { Get-Random }
Invoke-Command -ScriptBlock $func
The Invoke-Command
statement will execute the Script Block and generate random number.
We can also using Script Block for our own function such as:
Function Test() {
$FullName = [PSCustomObject]@{
FirstName = "John"
LastName = "Doe"
}
return $FullName
}
$func = { Test }
Invoke-Command -ScriptBlock $func
Please remember above script will behave differently if the function is directly enclosed inside Script Block like below:
$func = {
Function Test() {
$FullName = [PSCustomObject]@{
FirstName = "John"
LastName = "Doe"
}
return $FullName
} }
Invoke-Command -ScriptBlock $func
The above script won’t generate random number unlike the former. The reason is Script Block works for anonymous function inside braces {}
.
So, to make it work, either we enclose Test
function without body inside braces like former script or remove the function name to make it anonymous, then enclose it with braces {}
as follows:
$func = {
param($firstName, $lastName)
$FullName = [PSCustomObject]@{
FirstName = $firstName
LastName = $lastName
}
return $FullName
}
Invoke-Command -ScriptBlock $func -ArgumentList "John", "Doe"
Executing Script Block without storing it into a variable
We can execute Script Block directly without having to store into a variable as follows:
Invoke-Command -ScriptBlock {
param($firstName, $lastName)
$FullName = [PSCustomObject]@{
FirstName = $firstName
LastName = $lastName
}
return $FullName
} -ArgumentList "John", "Doe"
Alternatives for Executing Script Block
Besides using Invoke-Command
, we can also use call operator &
.
$func = {
param($firstName, $lastName)
$FullName = [PSCustomObject]@{
FirstName = $firstName
LastName = $lastName
}
return $FullName
}
& $func -firstName "John" -lastName "Doe"
Conclusion
In conclusion, Script Block enables us to create anonymous function. We can store Script Block in a variable or not and to execute we can use Invoke-Command
or call operator &
.