Script Blocks
Running a set of commands between curly braces doesn't actually execute them:
# Outputs 'Clear-Host; Get-ChildItem' rather than executing the commands
{Clear-Host; Get-ChildItem}
The block can be executed by prefixing with &:
# Clears the host and lists child items
&{Clear-Host; Get-ChildItem}
Blocks can also be assigned to variables:
$commands = {Clear-Host; Get-ChildItem}
&$commands
To get the return value of a script block, wrap it in parens:
Clear-Host
$value = {41 + 1}
"The result is {0}" -f (&$value) # Outputs 'The result is 42'
1 + &$value # Syntax error
If multiple commands are in a block, the first command not consumed will be returned:
# Outputs:
# Not returned
# Consumed the value 42
Clear-Host
$value = {42; Write-Host "Not returned"}
"Consumed the value {0}" -f (&$value)
Can use return to return a value, but any subsequent commands won't get executed:
# Outputs '42'
$value = {Clear-Host; return 42; Write-Host "This is ignored"}
&$value
One way to pass arguments to a script block is using the args array (useful if you have a variable number of arguments):
$qa = {
$question = $args[0]
$answer = $args[1]
Clear-Host
Write-Host "Here is your question: $question`nThe answer is: $answer"
}
&$qa "Is Powershell easy to learn?" "Yes!"
Here's the same block using the more readable params command:
$qa = {
param ($question, $answer)
Clear-Host
Write-Host "Here is your question: $question`nThe answer is: $answer"
}
# Can optionally pass by name, order doesn't matter
# Note that you don't have to specify the full name, could instead use
# -q and -a. Nice for one-off scripts but not as readable.
&$qa -answer "Yes!" -question "Is Powershell easy to learn?"
If a value is expected but not passed, by default it is converted to null. Can also explicitly check for an empty value:
$qa = {
param ($question, $answer)
if (!$answer) { $answer = "Error: You must give an answer!" }
Clear-Host
Write-Host "Here is your question: $question`nThe answer is: $answer"
}
&$qa "What is the meaning of life?"
Can also specify default values for params:
$qa = {
param ($question, $answer = "I don't know")
Clear-Host
Write-Host "Here is your question: $question`nThe answer is: $answer"
}
&$qa "What is the meaning of life?"
Can force params to specific types:
Clear-Host
$math = {
param ([int] $x, [int] $y)
return $x * $y
}
&$math 3 11
&$math 3 "x" # Error
Use process to enable pipelining:
Set-Location "C:\Temp"
$onlyTextFiles =
{
process
{
if ($_.Name -like "*.txt") { return $_.Name }
}
}
Clear-Host
Get-ChildItem | &$onlyTextFiles
Can optionally include begin and/or end blocks for pre-/post-processing:
Set-Location "C:\Temp"
$onlyTextFiles =
{
begin { $retval = "Here are the text files: `r`n"}
process
{
if ($_.Name -like "*.txt")
{
$retval =$retval + "`t" + $_.Name + "`r`n"
}
}
end { return $retval }
}
Clear-Host
Get-ChildItem | &$onlyTextFiles
Same example with param:
Set-Location "C:\Temp"
$onlyTextFiles =
{
param ($headertext = "Here are the text files")
begin { $retval = $headertext + ": `r`n" }
process
{
if ($_.Name -like "*.txt")
{
$retval = $retval + "`t" + $_.Name + "`r`n"
}
}
end { return $retval }
}
Clear-Host
Get-ChildItem | &$onlyTextFiles "Here are the files"