Можно ли автоматически передать параметр переключателя в функции PowerShell? - PullRequest
2 голосов
/ 22 марта 2020

Я создал функцию, вдохновленную здесь .

. Пока она работает, как и ожидалось, но только когда при вызове функции предусмотрен опциональный переключатель. То, что я хочу сделать, это просто иметь возможность набирать «Get-ExternalIP» без предоставления переключателя. Затем функция должна автоматически использовать переключатель -All. Кроме того, я не уверен, почему переключатель -All даже работает ...

Я пытался установить параметр $ All = $ true, он не работает, и VSCode сообщает мне, что он не рекомендуется в любом случае.

Есть ли способ автоматически передавать параметр -All Option Switch при вызове функции без каких-либо параметров? Кто-нибудь сможет объяснить, почему функция возвращает всю информацию, если указан ключ -All?

Спасибо!

Вот мой код:

function Get-ExternalIP {
  [CmdletBinding()]
  param (
    [parameter(Mandatory = $false)][switch]$Ip,
    [parameter(Mandatory = $false)][switch]$HostName,
    [parameter(Mandatory = $false)][switch]$City,
    [parameter(Mandatory = $false)][switch]$Region,
    [parameter(Mandatory = $false)][switch]$Country,
    [parameter(Mandatory = $false)][switch]$Location,
    [parameter(Mandatory = $false)][switch]$Provider,
    [parameter(Mandatory = $false)][switch]$PostalCode,
    [parameter(Mandatory = $false)][switch]$TimeZone,
    [parameter(Mandatory = $false)][switch]$All
  )

  $IpInfo = Invoke-RestMethod https://ipinfo.io/json

  switch ($PSBoundParameters.Values) {
    $Ip { $IpInfo.ip }
    $HostName { $IpInfo.hostname }
    $City { $IpInfo.city }
    $Region { $IpInfo.region }
    $Country { $IpInfo.country }
    $Location { $IpInfo.loc }
    $Provider { $IpInfo.org }
    $PostalCode { $IpInfo.postal }
    $TimeZone { $IpInfo.timezone }
    Default { $IpInfo }

  }

}

Get-ExternalIP

Ответы [ 4 ]

3 голосов
/ 22 марта 2020

Можно использовать наборы параметров по умолчанию для опции All:

[CmdletBinding(DefaultParameterSetName='Everything')]
param(
    [Parameter(ParameterSetName='Something')][switch]$Ip,
    [Parameter(ParameterSetName='Something')][switch]$HostName,
    [Parameter(ParameterSetName='Something')][switch]$City,
    [Parameter(ParameterSetName='Something')][switch]$Region,
    [Parameter(ParameterSetName='Something')][switch]$Country,
    [Parameter(ParameterSetName='Something')][switch]$Location,
    [Parameter(ParameterSetName='Something')][switch]$Provider,
    [Parameter(ParameterSetName='Something')][switch]$PostalCode,
    [Parameter(ParameterSetName='Something')][switch]$TimeZone,
    [Parameter(ParameterSetName='Everything')][switch]$All
)

# set up dictionary to hold the switch-name-to-ipinfo-names
$Options = [Ordered]@{
  'Ip' = 'ip'
  'HostName' = 'hostname'
  'City' = 'city'
  'Region' = 'region'
  'Country' = 'country'
  'Location' = 'loc'
  'Provider' = 'org'
  'PostalCode' = 'postal'
  'TimeZone' = 'timezone'
}

$IpInfo = Invoke-RestMethod https://ipinfo.io/json

# Select all options
$selected = $Options.Keys
if($PSCmdlet.ParameterSetName -ne 'Everything'){
    # 1 or more switches were passed, select only those options
    $selected = $selected.Where({$PSBoundParameters[$_]})
}

# Create a new object with the selected options as properties
$properties = [ordered]@{}
foreach($prop in $selected){
  $properties[$prop] = $IpInfo.($Options[$prop])
}

# return the new object
return [pscustomobject]$properties

Используя имя набора параметров, чтобы определить, выводить ли все (и затем возвращать), поведение одинаково независимо от того, о том, прошел ли пользователь -All или вообще не переключался.

3 голосов
/ 22 марта 2020

Я бы использовал $PSBoundParameters.Keys, так как ваши ключи правильно названы для соответствия возвращаемой информации:

function Get-ExternalIP {
    [CmdletBinding()]
    param (
        [parameter(Mandatory=$false)][switch]$Ip,
        [parameter(Mandatory=$false)][switch]$HostName,
        [parameter(Mandatory=$false)][switch]$City,
        [parameter(Mandatory=$false)][switch]$Region,
        [parameter(Mandatory=$false)][switch]$Country,
        [parameter(Mandatory=$false)][switch]$Location,
        [parameter(Mandatory=$false)][switch]$Provider,
        [parameter(Mandatory=$false)][switch]$PostalCode,
        [parameter(Mandatory=$false)][switch]$TimeZone,
        [parameter(Mandatory=$false)][switch]$All
    )
    $IpInfo = Invoke-RestMethod https://ipinfo.io/json
    if ($All) { return $IpInfo }

    # exclude Common Parameters
    $commonParams = 'Debug','ErrorAction','ErrorVariable','InformationAction','InformationVariable','OutVariable',
                    'OutBuffer','PipelineVariable','Verbose','WarningAction','WarningVariable','WhatIf','Confirm'

    $items = (@($PSBoundParameters.Keys) | Where-Object { $commonParams -notcontains $_ }) -replace
             'Location', 'loc' -replace 'Provider', 'org' -replace 'PostalCode', 'postal'

    $IpInfo | Select-Object $items
}

Как прокомментировал mklement0 , есть гораздо лучший способ извлечения использованных ключей, чем показано в приведенном выше коде.

Вместо фильтрации известных общих параметров имеет смысл проверить ключи $ PSBoundParameter по свойствам, возвращенным в объекте $ IpInfo.

$items = ($PSBoundParameters.Keys -replace 'Location', 'loc' -replace 'Provider', 'org' -replace 'PostalCode', 'postal').Where({ $_ -in $IpInfo.psobject.Properties.Name })
2 голосов
/ 22 марта 2020

ответ Матиаса Р. Джессена и ответ Тео обеспечивают элегантные решения; позвольте мне дополнить их ответом на ваш конкретный c вопрос:

Может ли кто-нибудь объяснить, почему функция возвращает всю информацию, если указан переключатель -All?

Ваш оператор switch имеет ветку Default, которая вызывается, если не выполняется ни одно из условий других ветвей; , поскольку у вас нет ветви для значения переключателя -All, обработчик Default запускает , если было указано
-All
.

Напротив, , если вы не передаете любой аргумент, оператор switch никогда не вводится , потому что для коллекционного значения , switch оператор неявно зацикливает на элементы этой коллекции. Без переданных аргументов $PSBoundParameters.Values - это пустая коллекция , поэтому перечислять нечего.

Подход с помощью набора параметров в ответе Матиаса - самое простое решение этой проблемы, которое имеет дополнительное преимущество, заключающееся в том, что переключатели -All и указанные свойства c имя-свойства взаимно исключают друг друга.

0 голосов
/ 22 марта 2020

Если вы напечатаете, что такое $ psboundparameters.values, вы увидите, что он пуст, если вы не используете «-all», в противном случае он имеет одно значение $ true.

...