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 worldIf 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.ObjectDefines 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 $aDefine 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 $displayExecutionEverything 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"