如何在PowerShell中使用多个参数强制执行高级函数的位置0
我正在将我的一个标准函数转换为高级函数。该函数基本上与我公司的服务器进行对话,并返回我需要的有关我们所拥有的产品的信息。目前,它被编码为只扫描所有服务器,但我想添加一些开关,其中MyFunc-all将扫描所有服务器,MyFunc-Single SERVERNAME将只扫描该服务器,MyFunc-Help将显示有关该函数的信息 我有工作的功能,如果你把一切都像你应该它的工作很好。我遇到的问题是,在运行函数时,强制某人在位置0处输入开关。就像我在没有开关的情况下调用函数一样,它要求为“All”提供一个值。如果我将值留空或输入任何内容,我会收到一条错误消息“无法处理参数'All'上的参数转换” 这是我第一次尝试高级功能,所以我确信我遗漏了一些东西,但我认为有一种方法需要位置0输入 我正在寻找的示例(如果可能) PS>MyFunc PS>“由于未提供交换机,我们被要求提供一个交换机” PS>-All或-Help或-Single SERVERNAME PS>打印结果如何在PowerShell中使用多个参数强制执行高级函数的位置0,powershell,Powershell,我正在将我的一个标准函数转换为高级函数。该函数基本上与我公司的服务器进行对话,并返回我需要的有关我们所拥有的产品的信息。目前,它被编码为只扫描所有服务器,但我想添加一些开关,其中MyFunc-all将扫描所有服务器,MyFunc-Single SERVERNAME将只扫描该服务器,MyFunc-Help将显示有关该函数的信息 我有工作的功能,如果你把一切都像你应该它的工作很好。我遇到的问题是,在运行函数时,强制某人在位置0处输入开关。就像我在没有开关的情况下调用函数一样,它要求为“All”提供一
function MyFunc
{
[CmdletBinding()]
PARAM(
[Parameter(Mandatory=$true, Position=0)]
[switch]$All,
[switch]$Help,
[switch]$Single,
[Parameter(ValueFromRemainingArguments=$true)]
[string]$ServerName
)
If($all)
{
$Servers = @("Server1",
"Server2",
"Server3",
"Server4",
"Server5")
#Check servers
}
elseif($Single)
{
$Servers = @($ServerName)
#Check server
}
elseif($Help)
{
#Print help message
}
}
我建议对调用函数和定义其参数的方式进行一些更改 首先,去掉
-Help
开关。PowerShell具有(非常好的)帮助语义,您应该使用这些语义。为函数定义,然后用户可以调用Get Help MyFunc
或Help MyFunc
查看函数的所有信息。最好的部分是,如果您只需要参数以及需要哪些参数,那么您不必做任何事情;它会自动为您生成(现在就开始尝试获取函数的帮助,不做任何更改)
其次,我的建议是避免在函数中静态定义服务器(对于-All
)。只需获取一个接受数组的-ServerName
参数,并让函数检查其中的任何内容。在PowerShell中,接受单个项目和阵列时,很容易实现这一点。使用高级功能,这也可以在管道上工作,只需进行最小的额外更改
这将使您的函数只剩下一个参数,同时让它保持同样的通用性。我的函数版本如下所示:
function MyFunc
{
[CmdletBinding()]
PARAM(
[Parameter(
ValueFromRemainingArguments=$true,
ValueFromPipeline=$true
)]
[string[]]
$ServerName
)
Process {
foreach ($server in $ServerName) {
# check this particular server
}
}
}
Get-Content -Path 'C:\List\Servers.txt' | MyFunc
以下是调用此函数的不同方法,所有函数都可以使用:
MyFunc 'SomeServer'
MyFunc 'Server4' 'Server5' 'Server6' # Spaces
MyFunc -ServerName 'ThisServer'
MyFunc -ServerName 'ThatServer','ThisServer','OtherServer'
'CoolServer' | MyFunc
'Server1','Server2','Server3' | MyFunc
函数的调用方可以使用预定义服务器列表
如果确实要预定义服务器列表,可以将它们放在单独的文本文件中,每行一个,然后执行以下操作:
function MyFunc
{
[CmdletBinding()]
PARAM(
[Parameter(
ValueFromRemainingArguments=$true,
ValueFromPipeline=$true
)]
[string[]]
$ServerName
)
Process {
foreach ($server in $ServerName) {
# check this particular server
}
}
}
Get-Content -Path 'C:\List\Servers.txt' | MyFunc
这就是在您的功能中支持管道的美妙之处
您还可以定义一个函数,该函数为您提供列表,其实现可能会在以后更改:
function Get-DefaultServerList {
[CmdletBinding()]
param()
@(
'Server1'
'Server2'
'Server3'
)
}
然后你可以做:
Get-DefaultServerList | MyFunc
重点是什么?您可以在以后更改该函数的定义,以(比如)从文件、web服务、注册表中获取其列表,无论什么。补充一些一般性建议:
- 要实现互斥参数,请使用参数集
- 看到和
- 不要强制使用
参数,除非这些参数用于选择(唯一地意味着使用)一个已定义的参数集。敬请见谅[switch]
- 对于整个函数,在所有参数集上,
es应该是可选的(并且应该始终默认为[switch]
,这是隐式的)$False
换句话说:应该至少有一个参数集不需要用户通过开关
- 对于整个函数,在所有参数集上,
- 使用基于注释的帮助,您的高级功能不仅可以自动使用
,还可以支持标准的获取帮助
参数来调用基本帮助(要获得更详细的帮助,必须使用-?
)获取帮助
- 看
- 尽可能避免
,PowerShell传递开放式相关值集的方法是使用数组参数,将值以逗号分隔传递给数组参数value from remainingarguments
-ServerName
参数更改为-ComputerName
Briantist的观点是不要将服务器名称硬编码到函数中,但我在这里这样做是为了说明参数集的使用:您可以使用
-All
或至少一个服务器名调用MyFunc
。使用参数集可确保不能同时执行这两项操作
<#
.SYNOPSIS
One-line description.
.DESCRIPTION
More detailed description
.PARAMETER All
Targets all servers.
.PARAMETER ComputerName
The name(s) of the server(s) to targets.
.EXAMPLE
> MyFunc -All
#>
function MyFunc {
[CmdletBinding(DefaultParameterSetName='Given', PositionalBinding=$False)]
param(
[Parameter(ParameterSetName='Given', Position=0, Mandatory, ValueFromPipeline)]
[string[]] $ComputerName
,
[Parameter(ParameterSetName='All', Mandatory)]
[switch] $All
)
begin {
# If -All was specified, determine the set of servers.
if ($PSCmdlet.ParameterSetName -eq 'All') {
$ComputerName = 'Server1', 'Server2'
}
}
process {
foreach ($server in $ComputerName) {
$server # process each server
}
}
}
MyFunc-All
#>
函数MyFunc{
[CmdletBinding(DefaultParameterSetName='Given',PositionBinding=$False)]
param(
[参数(ParameterSetName='Given',Position=0,必填,ValueFromPipeline)]
[字符串[]]$ComputerName
,
[参数(ParameterSetName='All',必填)]
[切换]$All
)
开始{
#如果指定了-All,请确定服务器集。
if($PSCmdlet.ParameterSetName-eq'All'){
$ComputerName='Server1','Server2'
}
}
过程{
foreach($ComputerName中的服务器){
$server#处理每台服务器
}
}
}
做得很好;可能值得一提的是,基于注释的帮助还为您提供自动的-?
参数支持。这一支持:MyFunc'Server1'、'Server2'、'Server3'
将无法与ValueFromRemainingArguments=$true
@PetSerAl正常工作:很好;详细说明:如果将其余参数指定为数组(逗号分隔),则必须显式使用参数名,即:MyFunc-ServerName Server1、Server2、Server3
。不带参数名,仅限