Currently, a script/function's parameter is only considered _bound_ if an actual value was supplied by the _caller_.
Notably, this means that parameter _default values_ are _not_ reflected in $PSBoundParameters
, which decreases its usefulness when the intent is to pass _all_ parameter values through to another command via splatting (@PSBoundParameters
).
If there's a good reason to keep the current behavior (if only for the sake of not making a breaking change), perhaps another automatic variable, such as $PSParametersWithValue
, could be introduced.
For a real-world example and workarounds, see this Stack Overflow question.
Yeah, I've written a function Get-ParameterValue
several times for this purpose. Particularly when splatting to another function it's awkward to have to deal with it by hand. It would be nice if there was a $PSNonEmptyParameters
or $PSParametersWithValues
or something.
There is a strong reason not to change the current behavior: the presence of a member in this collection tells you that the parameter was actually specified in the command call i.e. that the formal parameter was bound hence the name "PSBoundParameters". You'll have to add a new variable if you want different semantics.
Adding a new property is reasonable though - we have BoundPositionally
list of strings - we could a similar BoundDefaultValue
list.
I realize this issue has long been stale, but for those of us who want a realistic solution, I have implemented some rather simple boilerplate code for it.
foreach($key in $MyInvocation.MyCommand.Parameters.Keys){
$value = Get-Variable $key -ValueOnly -EA SilentlyContinue
if($value -and !$PSBoundParameters.ContainsKey($key)) {$PSBoundParameters[$key] = $value}
}
My alternate method didn't work as I anticipated. Sorry for not double-checking before posting.
Thanks, @True-Demon, but the issue is still open; it sounds like the plan is to eventually implement it, but it's unclear when.
As for your workarounds:
The first one is great, but I don't think the second one will work, though, because $MyInvocation.MyCommand.Parameters
contains only metadata, not values, from what I can tell.
@mklement0 That's why he calls get-variable 馃槈
Here's mine, which I mentioned earlier. It's basically the same thing, except that it merges with PSBoundParameters (and is in function form, so you can dot-source it, and includes tests to make _sure_ you dot-sourced it)
https://gist.github.com/Jaykul/c623c45d32329cadac9e7622937e1b76
@Jaykul:
That's why he calls get-variable
Yes, in the first snippet, which indeed works (as stated - though I'd use $null -ne $value
rather than just $value
as a slightly more robust conditional to infer the presence of a value from; it too modifies $PSBoundParameters
directly).
However, my comment was about the second snippet, which I interpret to make the claim that $MyInvocation.MyCommand.Parameters
would essentially already give us what this issue requests as an enhancement, which is not the case; specifically, I was referring to:
you can use the native $MyInvocation.MyCommand.Parameters, which contains all parameter keys & values, bound, null, default, or otherwise
My point was that $MyInvocation.MyCommand.Parameters
seemingly contains just metadata, not values (neither bound nor default ones).
Thanks for sharing your Gist, which is a nicely packaged solution.
Sounds like we have viable workarounds now.
Let's hope that we soon won't need them anymore.
You're right, I made the mistake of assuming before I posted that. I've omitted that since it doesn't apply in order to prevent leading others astray.
Most helpful comment
Adding a new property is reasonable though - we have
BoundPositionally
list of strings - we could a similarBoundDefaultValue
list.