Powershell “special” switch parameter

别说谁变了你拦得住时间么 提交于 2020-04-28 09:58:31

问题


I have the powershell function below

Function Test
{
    Param
    (               
        [Parameter()]
        [string]$Text = "default text"
    )

    Write-Host "Text : $($Text)"
}

And I would like to be able to call this function like below :

Test -Text : should display the default text on the host

Test -Text "another text" : should display the provided text on the host

My issue is that the first syntax is not allowed in powershell ..

Any ideas of how I can achieve this goal ? I would like a kind of 'switch' parameter that can take values other than boolean.

Thanks


回答1:


The problem you're running into is with parameter binding. PowerShell is seeing [string] $Text and expecting a value. You can work around this like so:

function Test {
    param(
        [switch]
        $Text,

        [Parameter(
            DontShow = $true,
            ValueFromRemainingArguments = $true
        )]
        [string]
        $value
    )

    if ($Text.IsPresent -and [string]::IsNullOrWhiteSpace($value)) {
        Write-Host 'Text : <default text here>'
    }
    elseif ($Text.IsPresent) {
        Write-Host "Text : $value"
    }
}

Note: this is a hacky solution and you should just have a default when parameters aren't passed.




回答2:


TheIncorrigible1's helpful answer provides a workaround for a single parameter, via a catch-all parameter that collects all positionally passed arguments via the ValueFromRemainingArguments parameter property.

Fundamentally, though, what you're asking for is unsupported in PowerShell:

PowerShell has no support for parameters with optional values as of 7.0 - except for [switch] parameters.

That is:

  • Any parameter you declare with a type other than [switch] invariably requires a value (argument).

  • The only other option is to indiscriminately collect any unbound positional arguments in a ValueFromRemainingArguments-tagged parameter, but you won't be able to associate these with any particular other bound parameter.

In other words:

  • If you happen to need just one optional-argument parameter, the ValueFromRemainingArguments can work for you (except that you should manually handle the case of mistakenly receiving multiple values), as shown in TheIncorrigible1's answer.

  • If you have two or more such parameters, the approach becomes impractical: you'd have to know in which order the parameters were passed (which PowerShell doesn't tell you) in order to associate the remaining positional arguments with the right parameters.


With [switch] parameters (using an imagined -Quiet switch as an example):

  • The default value - if you just pass -Quiet -is $true.
  • $false is typically indicated by simply not specifying the switch at all (that is, omitting -Quiet)

However, you may specify a value explicitly by following the switch name with :, followed by the Boolean value:

  • -Quiet:$true is the same as just -Quiet

  • -Quiet:$false is typically the same as omitting -Quiet; in rare cases, though, commands distinguish between an omitted switch and one with an explicit $false value; notably, the common -Confirm parameter allows use of -Confirm:$false - as opposed to omission of -Confirm - to override the value of the $ConfirmPreference preference variable.

While : as the separator between the parameter name and its argument (as opposed to the usual space char.) is supported with all parameters, with [switch] parameters it is a must so as to unequivocally signal that what follows is an argument for the switch parameter (which by default needs no argument) rather than an independent, positional argument.


The above tells us that PowerShell already has the syntax for general support of optional-argument parameters, so at some point in the future it could support them with any data type, as suggested in this GitHub issue.



来源:https://stackoverflow.com/questions/58838941/powershell-special-switch-parameter

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