about_Parameter_Sets

簡短描述

描述如何在進階函式中定義和使用參數集。

詳細描述

PowerShell 會使用參數集來撰寫單一函式,以針對不同的案例執行不同的動作。 參數集可讓您向用戶公開不同的參數。 而且,根據使用者指定的參數傳回不同的資訊。 您一次只能使用一個參數集。

參數集需求

下列需求適用於所有參數集。

  • 如果未為參數指定任何參數集,參數會屬於所有參數集。

  • 每個參數集都必須有唯一的參數組合。 可能的話,至少其中一個唯一參數應該是必要參數。

  • 包含多個位置參數的參數集必須為每個參數定義唯一的位置。 沒有兩個位置參數可以指定相同的位置。

  • 集合中只有一個參數可以宣告 ValueFromPipeline 具有 值的 true關鍵詞。 多個參數可以使用的值true來定義 ValueFromPipelineByPropertyName 關鍵詞。

注意

有32個參數集的限制。

預設參數集

定義多個參數集時,DefaultParameterSetNameCmdletBinding 屬性的 關鍵詞會指定預設參數集。 當 PowerShell 無法根據提供給命令的資訊來判斷要使用的參數集時,PowerShell 會使用預設參數集。 如需 CmdletBinding 屬性的詳細資訊,請參閱about_Functions_CmdletBindingAttribute

宣告參數集

若要建立參數集,您必須為參數集中的每個參數指定 ParameterSetName Parameter屬性的關鍵詞。 對於屬於多個參數集的參數,請為每個參數集新增 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。 和 LiteralPathAll 參數集也是如此LiteralPath。 雖然 PathAllLiteralPathAll 參數集都有 All 參數, 但 PathLiteralPath 參數仍會加以區分。

使用 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 參數對 Cmdlet 的不同參數集而言是唯一的。Get-ChildItem 當參數在相同的 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