How to pass the 'argument-line' of one PowerShell function to another?
I believe this:
function myls { Write-Output "hello!"; iex "Get-ChildItem @args"}
will come closer to producing the expected result.
Update: There is apparently a known bug with using @args in this manner to pass named parameters:
https://connect.microsoft.com/PowerShell/feedback/details/368512/splat-operator-args-doesnt-properly-pass-named-arguments?wa=wsignin1.0
I'd discontinue using that until it's resolved.
Making a wrapper properly is not that easy, unfortunately. First of all, the splat operator should presumably be applied to a hashtable (e.g. automatic PSBoundParameters
or another), not to the array $args
directly.
There are at least two options (both are not perfect), and a hack (see the update section).
Option 1. Use the "classic" way of making a wrapper. Example: see how this is done for the function help
which is a wrapper of the Get-Help
cmdlet:
Get-Content function:\help
You can see that the wrapper function declarers all the parameters that the wrapped cmdlet has in order to have that PSBoundParameters
bounded to the existing function parameters.
Your example. If your function declares the parameter Exclude
then the example code starts to work. But it works for Exclude
only, not Force
, though Force
is also passed in:
function myls($Exclude) {
# only Exclude is in $PSBoundParameters even though we send Force, too:
$PSBoundParameters | Out-String | Out-Host
Write-Output "hello!"
Get-ChildItem @PSBoundParameters
}
cd d
myls -Exclude b -Force
Option 2. In theory in should be possible to build a hashtable from the array $args
manually and apply the splat operator to it. But this task does not look practically attractive.
UPDATE
Well, there is actually yet another ad-hoc option (pure hack!) that requires minimum effort and will work in some trivial, mostly interactive, scenarios. It is not for somehow serious code!
function myls {
# extra job
Write-Output "hello!"
# invoke/repeat the calling code line with myls "replaced" with Get-ChildItem
Set-Alias myls Get-ChildItem
Invoke-Expression $MyInvocation.Line
}
cd d
# variables can be used as the parameter values, too
$exclude = 'b'
myls -Exclude $exclude -Force
If you want a drop-in wrapper for ls, you should write a proper Proxy Command. There are a couple of versions of the generator on PoshCode.org, including the one from Lee Holmes' PowerShell Cookbook,
But the proxy command generator is built in now, so you can just write:
$CommandName = "Get-ChildItem"
$Command = Get-Command $CommandName
[System.Management.Automation.ProxyCommand]::Create($Command)