Instead of run1 $args
, use run1 @args
, i.e. splatting with the automatic $args
variable.
That way, whatever arguments are passed to the run1.ps1
script - whether named or positional - are correctly passed through to the run1
function.
- Caveat: This does not work for pass-through
[switch]
arguments with an explicit value (which is rare, however). For instance, if you were to invoke run1.ps1
with -rec:$false
(instead of simply omitting this argument), -rec
and $false
would mistakenly be passed as two arguments, and $rec
would end up being $true
.
Note:
No user-defined array can provide this functionality[1] - the automatic $args
array has magic built in that enables this functionality; splatting with a user-defined array only supports passing positional arguments through, and that wouldn't work in your case, because [switch]
parameters are always named (non-positional).
For splatting based on user-defined variables that supports passing named arguments, hashtable-based splatting is necessary.
As an aside:
If you make your function an advanced one (in the simplest case by decorating the param(...)
block with [CmdletBinding()]
), it'll ensure that no extra arguments are passed (ones that don't bind to predefined parameters), for added robustness.
If you additionally make your script an advanced one - which requires defining parameters explicitly for the script itself too - you can pass the script's parameter values through via the automatic $PSBoundParameters
variable variable, i.e. with run1 @PSBoundParameters
. This would also avoid the [switch]
-related bug mentioned above. This answer shows an example of $PSBoundParameters
-based splatting in the context of a proxy (wrapper) function around Write-Host
.
[1] As Santiago Squarzon points out, there a limited way to make this work, but it is both highly obscure and more cumbersome than using a hashtable for splatting and therefore not worth considering.
For the sake of completeness: To have an array element represent a parameter name, use a dummy string decorated with a NoteProperty member literally named <CommandParameterName>
whose value is the target parameter name (with or without the -
prefix). A minimal example that is the equivalent of
Get-ChildItem -Directory -LiteralPath \
:
$arr = ('' | Add-Member -PassThru '<CommandParameterName>' 'Directory'), ('' | Add-Member -PassThru '<CommandParameterName>' 'LiteralPath'), '\'; Get-ChildItem @arr
In fact, this technique is behind the magic of @args
, as the following example shows:
function foo { $args | % { "`n---`n[$_]"; $_ | Get-Member -Type NoteProperty -Force } }; foo -param1 val1