[英]Is it possible to automatically pass along a switch parameter in a PowerShell Function?
I created a function with some inspiration from here .我从这里获得了一些灵感,创建了一个函数。
It's working as expected so far but only when an Option Switch is provided when calling the function.到目前为止,它按预期工作,但只有在调用函数时提供了选项开关。 What I want to do is just be able type "Get-ExternalIP" without providing a switch.
我想要做的只是能够在不提供开关的情况下输入“Get-ExternalIP”。 The function should then automatically use the -All switch.
然后该函数应自动使用 -All 开关。 Also I'm not sure why the -All switch even works...
另外我不确定为什么 -All 开关甚至可以工作......
I've tried to set the Parameter $All = $true it's not working and VSCode tells me that it's not recommended anyways.我试图设置参数 $All = $true 它不起作用并且 VSCode 告诉我无论如何都不推荐它。
Is there a way to automatically pass along the -All Option Switch when the function is called without any parameters?有没有办法在不带任何参数的情况下调用函数时自动传递 -All 选项开关? Would somebody be able to explain why the function returns all info if the -All switch is specified?
如果指定了 -All 开关,有人能解释为什么该函数返回所有信息吗?
Thanks!谢谢!
Here's my code:这是我的代码:
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
You could use parameter sets to default to the All
option:您可以使用参数集默认为
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
By using the parameter set name to determine whether to output everything (and then return), the behavior is the same regardless of whether the user passes -All
, or no switches at all.通过使用参数集名称来确定是否输出所有内容(然后返回),无论用户是否通过
-All
或根本没有开关,行为都是相同的。
I would use the $PSBoundParameters.Keys
as your switches are properly named to match the returned info:我会使用
$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
}
As mklement0 commented, there is a much better way of retrieving the used switches than shown in the above code.正如mklement0评论的那样,有一种比上面代码中显示的更好的检索使用的开关的方法。
Instead of filtering out the known Common Parameters, it makes more sense to check the $PSBoundParameter keys against the properties returned in the $IpInfo object.与其过滤掉已知的通用参数,不如根据 $IpInfo 对象中返回的属性检查 $PSBoundParameter 键更有意义。
$items = ($PSBoundParameters.Keys -replace 'Location', 'loc' -replace 'Provider', 'org' -replace 'PostalCode', 'postal').Where({ $_ -in $IpInfo.psobject.Properties.Name })
Mathias R. Jessen's answer and Theo's answer provide elegant solutions; Mathias R. Jessen 的回答和Theo 的回答提供了优雅的解决方案; let me complement them with an answer to your specific question:
让我用你的具体问题的答案来补充它们:
Would somebody be able to explain why the function returns all info if the
-All
switch is specified?如果指定了
-All
开关,有人能解释为什么该函数返回所有信息吗?
Your switch
statement has a Default
branch, which is invoked if none of the other branches' conditions are met;你的
switch
语句有一个Default
分支,如果其他分支的条件都不满足,就会调用它; since you don't have a branch for the -All
switch value, the Default
handler kicks in if由于您没有用于
-All
开关值的分支,因此Default
处理程序将启动,如果-All
was specified . -All
被指定。
By contrast, if you don't pass any argument, the switch
statement is never entered , because, for collection-valued input, the switch
statement implicitly loops over the elements of that collection.相比之下,如果您不传递任何参数,则永远不会输入
switch
语句,因为对于集合值输入, switch
语句隐式地遍历该集合的元素。 With no arguments passed, $PSBoundParameters.Values
is an empty collection , so there is nothing to enumerate.没有传递参数,
$PSBoundParameters.Values
是一个空集合,所以没有什么可枚举的。
The parameter-set approach in Mathias' answer is the simplest solution to this problem, which has the added advantage of making the -All
switch and the specific property-name switches mutually exclusive. Mathias 回答中的参数集方法是解决此问题的最简单方法,它具有使
-All
开关和特定属性名称开关互斥的额外优势。
如果你打印出 $psboundparameters.values 是什么,当你不使用“-all”时你会看到它是空的,否则它只有一个 $true 值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.