about_Parameter_Sets

简短说明

介绍了如何在高级函数中定义和使用参数集。

长说明

PowerShell 使用参数集,允许你编写可以针对不同方案执行不同操作的单个函数。 参数集使你能够向用户公开不同的参数。 另外,可以根据用户指定的参数返回不同的信息。 一次只能使用一个参数集。

参数集要求

以下要求适用于所有参数集。

  • 如果某个参数未指定有参数集,则该参数属于所有参数集。

  • 每个参数集必须具有唯一的参数组合。 如果可能,应该至少有一个唯一参数是必需的参数。

  • 包含多个位置参数的参数集必须为每个参数定义唯一位置。 两个位置参数不能指定同一位置。

  • 一个集内只有一个参数可以声明值为 trueValueFromPipeline 关键字。 多个参数可以定义值为 trueValueFromPipelineByPropertyName 关键字。

注意

参数集的数量限制为 32 个。

默认参数集

定义了多个参数集时,CmdletBinding 属性的 DefaultParameterSetName 关键字将指定默认参数集。 当 PowerShell 无法根据提供给命令的信息确定所要使用的参数集时,它会使用默认参数集。 有关 CmdletBinding 属性的详细信息,请参阅 about_Functions_CmdletBindingAttribute

声明参数集

若要创建参数集,必须为参数集中的每个参数指定 Parameter 属性的 ParameterSetName 关键字。 对于属于多个参数集的参数,请为每个参数集添加 Parameter 属性

使用 Parameter 属性,可以为每个参数集采用不同的方式来定义参数。 例如,可以将某个参数定义为在一个集内是必需的,在另一个集内是可选的。 但是,每个参数集必须至少包含一个唯一参数。

未分配参数集名称的参数属于所有参数集。

示例

以下示例函数统计一个文本文件中的行数、字符数和单词数。 使用参数,你可以指定要返回哪些值以及要度量哪些文件。 定义了四个参数集:

  • 路径
  • PathAll
  • LiteralPath
  • LiteralPathAll
function Measure-Lines {
    [CmdletBinding(DefaultParameterSetName = 'Path')]
    param (
        [Parameter(Mandatory, ParameterSetName = 'Path', Position = 0)]
        [Parameter(Mandatory, ParameterSetName = 'PathAll', Position = 0)]
        [string[]]$Path,

        [Parameter(Mandatory, ParameterSetName = 'LiteralPathAll', ValueFromPipeline)]
        [Parameter(Mandatory, ParameterSetName = 'LiteralPath', ValueFromPipeline)]
        [string[]]$LiteralPath,

        [Parameter(ParameterSetName = 'Path')]
        [Parameter(ParameterSetName = 'LiteralPath')]
        [switch]$Lines,

        [Parameter(ParameterSetName = 'Path')]
        [Parameter(ParameterSetName = 'LiteralPath')]
        [switch]$Words,

        [Parameter(ParameterSetName = 'Path')]
        [Parameter(ParameterSetName = 'LiteralPath')]
        [switch]$Characters,

        [Parameter(Mandatory, ParameterSetName = 'PathAll')]
        [Parameter(Mandatory, ParameterSetName = 'LiteralPathAll')]
        [switch]$All,

        [Parameter(ParameterSetName = 'Path')]
        [Parameter(ParameterSetName = 'PathAll')]
        [switch]$Recurse
    )

    begin {
        if ($All) {
            $Lines = $Words = $Characters = $true
        }
        elseif (($Words -eq $false) -and ($Characters -eq $false)) {
            $Lines  = $true
        }
    }
    process {
        if ($Path) {
            $Files = Get-ChildItem -Path $Path -Recurse:$Recurse -File
        }
        else {
            $Files = Get-ChildItem -LiteralPath $LiteralPath -File
        }
        foreach ($file in $Files) {
            $result = [ordered]@{ }
            $result.Add('File', $file.fullname)

            $content = Get-Content -LiteralPath $file.fullname

            if ($Lines) { $result.Add('Lines', $content.Length) }

            if ($Words) {
                $wc = 0
                foreach ($line in $content) { $wc += $line.split(' ').Length }
                $result.Add('Words', $wc)
            }

            if ($Characters) {
                $cc = 0
                foreach ($line in $content) { $cc += $line.Length }
                $result.Add('Characters', $cc)
            }

            New-Object -TypeName psobject -Property $result
        }
    }
}

每个参数集必须具有唯一的参数或唯一的参数组合。 PathPathAll 参数集非常相似,但 All 参数对于 PathAll 参数集是唯一的。 对于 LiteralPathLiteralPathAll 参数集也是如此。 尽管 PathAllLiteralPathAll 参数集都具有 All 参数,但 Path 和 LiteralPath 参数可以区分它们。

使用 Get-Command -Syntax 可显示每个参数集的语法。 但是,此命令不会显示参数集的名称。 以下示例显示每个参数集中可以使用哪些参数。

(Get-Command Measure-Lines).ParameterSets |
  Select-Object -Property @{n='ParameterSetName';e={$_.name}},
    @{n='Parameters';e={$_.ToString()}}
ParameterSetName Parameters
---------------- ----------
Path             [-Path] <string[]> [-Lines] [-Words] [-Characters] [-Recurse] [<CommonParameters>]
PathAll          [-Path] <string[]> -All [-Recurse] [<CommonParameters>]
LiteralPath      -LiteralPath <string[]> [-Lines] [-Words] [-Characters] [<CommonParameters>]
LiteralPathAll   -LiteralPath <string[]> -All [<CommonParameters>]

操作中的参数集

示例使用 PathAll 参数集。

Measure-Lines test* -All
File                       Lines Words Characters
----                       ----- ----- ----------
C:\temp\test\test.help.txt    31   562       2059
C:\temp\test\test.md          30  1527       3224
C:\temp\test\test.ps1          3     3         79
C:\temp\test\test[1].txt      31   562       2059

使用来自多个集的参数时出错

此示例使用了来自不同参数集的唯一参数。

Get-ChildItem -Path $PSHOME -LiteralPath $PSHOME
Get-ChildItem: Parameter set cannot be resolved using the specified named
parameters. One or more parameters issued cannot be used together or an
insufficient number of parameters were provided.

Path 和 LiteralPath 参数对于 Get-ChildItem cmdlet 的不同参数集是唯一的。 当这些参数在同一个 cmdlet 中一起运行时,会引发错误。 对于每个 cmdlet 调用,一次只能使用一个参数集。

如何知道使用哪个参数集

自动变量 $PSCmdlet 提供 ParameterSetName 属性。 此属性包含正在使用的参数集的名称。 可以在函数中使用此属性来确定使用哪个参数集来选择特定于参数集的行为。

function Get-ParameterSetName {

    [CmdletBinding(DefaultParameterSetName = 'Set1')]
    param (
        [Parameter(ParameterSetName = 'Set1', Position = 0)]
        $Var1,

        [Parameter(ParameterSetName = 'Set2', Position = 0)]
        $Var2,

        [Parameter(ParameterSetName = 'Set1', Position = 1)]
        [Parameter(ParameterSetName = 'Set2', Position = 1)]
        $Var3,

        [Parameter(Position = 2)]
        $Var4
    )

    "Using Parameter set named '$($PSCmdlet.ParameterSetName)'"

    switch ($PSCmdlet.ParameterSetName) {
        'Set1' {
            "`$Var1 = $Var1"
            "`$Var3 = $Var3"
            "`$Var4 = $Var4"
            break
        }
        'Set2' {
            "`$Var2 = $Var2"
            "`$Var3 = $Var3"
            "`$Var4 = $Var4"
            break
        }
    }
}

PS> Get-ParameterSetName 1 2 3

Using Parameter set named 'Set1'
$Var1 = 1
$Var3 = 2
$Var4 = 3

PS> Get-ParameterSetName -Var2 1 2 3

Using Parameter set named 'Set2'
$Var2 = 1
$Var3 = 2
$Var4 = 3