I have a script (let's call it caller.ps1) that invokes another script callee.ps1. In caller.ps1, I want to inspect some arguments and pass them on, along with some other arguments to callee.ps1
caller:
param (
[Parameter(Mandatory, ParameterSetName="ByA")][string]$a, // passthru
[Parameter(Mandatory, ParameterSetName="ByB")][string]$b, // passthru
// some more passthru parameters
[Parameter()][switch]$inspect, // inspect, then pass on
[Parameter()][switch]$consume // consume, do not pass on
)
callee:
param (
[Parameter(Mandatory, ParameterSetName="ByA")][string]$a,
[Parameter(Mandatory, ParameterSetName="ByB")][string]$b,
// some more parameters
[Parameter()][switch]$i开发者_开发技巧nspect
)
what's the best practice here? I have tried @args
but it looks like it's empty. I suppose that's because all the arguments are bound to names?
Since I have two ParameterSets "ByA" and "ByB", and a bunch of switch parameters, it'd be super clunky to inspect each one and compose a new argument list for callee. Is there an elegant way of doing this? Thanks.
The automatic variable $PSBoundParameters
is very useful in this case, it will allow you to pass through the same arguments to the next scriptblock as long as the parameters name from the callee either have the same name or have aliases that match the ones from the caller.
Using 2 scriptblocks to demonstrate but the logic is exactly the same as with 2 .ps1
files.
$caller = {
param (
[Parameter(Mandatory, ParameterSetName="ByA")]
[string] $a,
[Parameter(Mandatory, ParameterSetName="ByB")]
[string] $b,
[Parameter()]
[switch] $inspect,
[Parameter()]
[switch] $consume
)
# remove the bound parameter before calling the next script
$null = $PSBoundParameters.Remove('consume')
# do whatever you need here with `$consume` then
# call the next script using the bounded parameters
& $callee @PSBoundParameters
}
$callee = {
param (
[Parameter(Mandatory, ParameterSetName="ByA")]
[string] $a,
[Parameter(Mandatory, ParameterSetName="ByB")]
[string] $b,
[Parameter()]
[switch] $inspect
)
$PSBoundParameters
}
& $caller -a 'hey there' -inspect -consume
As for why $args
didn't work, as the documentation states, $args
only works on undeclared parameters and your scripts are using a param
block (declared parameters) and will not allow undeclared ones because these are advanced scriptblocks / functions in a sense due to the Parameter
attribute declarations.
A simple example to visualize what this means:
In this example, the scriptblock only has 2 declared parameters and 3 arguments being passed, 1 and 2 are bound to the declared parameters and 3 is passed as an undeclared parameter hence is bound to $args
:
# works fine, outputs 3
& {param($paramA, $paramB) $args } -paramA 1 -paramB 2 3
Now if we try to do the same with an advanced scriptblock we will see an error because these don't allow undeclared parameters:
# Fails: A positional parameter cannot be found that accepts argument '3'.
& {[CmdletBinding()]param($paramA, $paramB) $args } -paramA 1 -paramB 2 3
精彩评论