How to pass a switch parameter as a variable / via splatting in PowerShell?

戏子无情 提交于 2021-02-07 07:16:48

问题


If you have multiple parameters which require a value when calling a command or a script, I know you can pass it like this:

$parameters = @{
    name = "John"
    last_name = "Doe"
}

But if the command or script actually just expect -T to indicate something like a flag, but the parameter itself doesn't require a value. How can I set that in a variable?

$optionalT = ""
if ($itNeedsTheT) $optionalT = "-T"

command $optionalT

If I do it like that it complains with the following message:

Unknown argument 'T' on command line.

回答1:


tl;dr

# Pass the $itNeedsT Boolean - which indicates whether the -T switch should
# be passed - as the switch's *value*.
command -T:$itNeedsTheT  

If $itNeedsTheT is $false, the above is the same as omitting -T - usually (read on for details).

Note the need to use : to separate the switch name from the value.


As boxdog points out in a comment, in a hashtable used with splatting (@parameters), you use a Boolean value to represent a switch parameter (a flag-like parameter of type [switch]) .

# Dynamically determine if -Recurse should be turned on.
$recurseIfTrue = $true

# Define the hashtable for splatting...
$parameters = @{
  Path = '.'
  Recurse = $recurseIfTrue  # turn the -Recurse switch on or off
}

# ... and pass it to the target command.
# *Loosely speaking*, the following command is the same as either:
#   Get-ChildItem -Path '.' -Recurse  # if $recuseIfTrue was $true
# or:
#   Get-ChildItem -Path '.'           # if $recuseIfTrue was $false
Get-ChildItem @parameters

That is, loosely speaking:

  • use $true to pass the switch
  • use $false to not pass the switch.

This allows you to keep a single hashtable definition that unconditionally includes the switch parameter, but whose value can determine programmaticaly.

Caveat:

Strictly speaking, hashtable entry Recurse = $true translates to parameter -Recurse:$true and Recurse = $false doesn't translate into omitting the parameter, it translates to passing -Recurse:$false.

In most cases, omitting a switch -Foo and passing it with value $false - i.e. -Foo:$false - are equivalent.

However, commands can detect the difference and sometimes act differently:

A notable example is the -Confirm common (switch) parameter: omitting -Confirm means that the $ConfirmPreference preference variable is respected, whereas -Confirm:$false means that the preference variable should be overridden (and confirmation should not be requested).

If you want to make this distinction yourself in a PowerShell script or function, you can call $PSBoundParameters.ContainsKey('Foo') in addition to checking the $Foo (-Foo) switch parameter variable's value.

If you're dealing with such a command and you want to programmatically enforce omission of a switch parameter, you'll have no choice but to conditionally add an entry for this switch, in a separate step:

# Dynamically determine if -Recurse should be turned on.
$recurseIfTrue = $true

# A 'Recurse' key now can NOT be included unconditionally,
# if you want to *omit* -Recurse in case $recurseIfTrue is $false
$parameters = @{
  Path = '.'
}

# Add a 'Recurse' entry only if the switch should be passed.
if ($recurseIfTrue) {
  $parameters.Recurse = $true
}

Get-ChildItem @parameters

Finally, note that as an alternative to specifying a switch value programmatically via splatting, you can pass a dynamic value to a switch directly:

# Dynamically determine if -Recurse should be turned on.
$recurseIfTrue = $true

Get-ChildItem -Path . -Recurse:$recurseIfTrue

Note the need to use : to separate the switch name from its value.

This is necessary, because using the customary whitespace to separate the parameter name from its value would cause PowerShell to interpret the Boolean as the next argument, given that switch parameters normally do not take values.

Although rarely used, this :-based syntax works with all parameter types.




回答2:


When splatting, create the hashtable with non-conditional parameters (the values can be variable), but add the optional parameters after the hashtable is created:

$parameters = @{
  Name = "John"
  LastName = "Doe"
  Age = $age
  Enabled = $true
}

if( $favoriteThing ){
  $parameters.FavoriteThing = $favoriteThing
}

command @parameters

If dealing with a switch in splatting, you can treat it as a boolean parameter like shown above, just give it a value of $true or $false depending on whether you want the switch to be enabled on the command or not. You can see a non-splat example of this to set a -Confirm flag to $false:

Install-Package some_package -Confirm:$false


来源:https://stackoverflow.com/questions/58507217/how-to-pass-a-switch-parameter-as-a-variable-via-splatting-in-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!