Writing a function with Action in PowerShell
I wanted to write a function that has an action parameter. The goal is to write functions that have the following features:
- Implement a dry-run feature
- Print the command with resolved variables
For example,
Run({echo "hello $some"});
Result
some
= “world”
[Command] echo "hello world"
hello world
If you configure dry-run
[Command] echo "hello world"
How to pass an action
Write a parameter. No special consideration required.
function Run {
param($action)
:
}
Next question comes to mind is, which type is it? It is ScriptBlock
type. I didn’t know the type, however, it looks better approach than System.Action
in PowerShell.
function Run {
param($action)
echo $action.GetType()
}
Run({echo "hello $dryRun"})
Result
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True ScriptBlock System.Object
Defines what a script block is and explains how to use script blocks in the PowerShell programming language.
For more details, refer to the following official documentation.
about Script Blocks — PowerShell | Microsoft Learn
How to run Script Block
Use the Script Block like following:
$a = {Get-Service BITS}
Invoke-Command -ScriptBlock $a
Define the Script Block with {...}
For Execution, you can use Invoke-Command
Command let. For simplify the command, you can use invoke()
method as well.
Invoke-Command -ScriptBlock $action
$action.Invoke()
How to substitute variables?
ScriptBlock.ToString()
method returns the ScriptBlock
commands.
$some = "world"
$action = { echo "hello $some" }
echo $action.ToString()
Result
echo "hello $some"
I want to substitute some
as world.
Use the $ExecutionContext.InvokeCommand.ExpandString()
$displayExecution = $ExecutionContext.InvokeCommand.ExpandString($action.ToString())
echo $displayExecution
Everything you wanted to know about variable substitution in strings — PowerShell | Microsoft Learn
Result
echo "hello world"
I’ve got something I wanted.
param($dryRun = "false")
function Run {
param($action)
$displayExecution = $ExecutionContext.InvokeCommand.ExpandString($action.ToString())
echo "[Command] $dispalyExecution" if ($dryRun -eq "false") {
$action.Invoke() }
}$some = "world"Run({echo "hello $some"})
Result
> .\actionSpike.ps1
[Command] echo "hello world"
hello world
> .\actionSpike.ps1 -dryRun "true"
[Command] echo "hello world"