Question
Hi, I'd like to dynamically create functions from a hashtable in Powershell. But the created functions are supposed to be able to receive parameters.
The Code I have so far:
$functions = @{
"wu" = "winget upgrade --include-unknown";
"wui" = "winget upgrade -i -e";
"wi" = "winget install -i";
"wii" = "winget install -i -e";
"ws" = "winget search"
}
foreach($funcName in $functions.PSBase.Keys){
New-Item function:\ -Name $funcName -Value $([scriptblock]::Create($functions[$funcName])) | Out-Null
}
The problem is, that whatever I type behind the function is not considered a parameter:
Can you help me out?
CodePudding user response:
Here is a possible solution:
$functions = @{
ws = { winget search $args }
# ... and so on
}
foreach($funcName in $functions.PSBase.Keys){
New-Item function:\ -Name $funcName -Value $functions.$funcName | Out-Null
}
- Define script blocks
{…}
directly in the hashtable, so you don't need to convert anything for theNew-Item
arguments. - Use the automatic variable
$args
to forward arguments of the script block to the command. Note that for native commands, the$args
array is unrolled automatically. For PowerShell commands you'd have to use splatting (@args
).
CodePudding user response:
Append @args
to your CLI calls, so that PowerShell passes all arguments passed to the function itself through:
foreach($funcName in $functions.PSBase.Keys){
$null = New-Item function:$funcName -Value "$($functions[$funcName]) @args"
}
Note:
@arg
is the splatted form of the automatic$args
variable. Given that you're calling external programs,$args
would be sufficient in this case (either form results in the (stringified) array elements being passed as individual arguments), but if you were to call PowerShell commands,@args
is required in order to pass named arguments through properly.As shown above, you can pass the function body as a string to
New-Item
- it'll be converted to a script block automatically.The above assumes that all pass-through arguments go at the end of each of the CLI command lines that make up your functions. If you need more fine-grained control, use the technique shown in zett42's helpful answer, which allows you to control for each CLI call where
@args
/$args
goes or alternatively allows you to declare parameters explicitly with aparam(...)
block.