about_Functions_Advanced_Parameters

简短说明

介绍如何向高级函数添加参数。

长说明

可以向自己编写的高级函数添加参数,并使用参数属性和参数来限制函数用户随参数提交的参数值。

除了 PowerShell 自动添加到所有 cmdlet 和高级函数的常用参数之外,添加到函数的参数也可供用户使用。 有关 PowerShell 通用参数的更多信息,请参阅 about_CommonParameters

从 PowerShell 3.0 开始,可以使用 @Args 散列传递来表示命令中的参数。 散列传递对于简单和高级函数都有效。 有关更多信息,请参阅 about_Functionsabout_Splatting

参数值的类型转换

将字符串作为参数提供给需要不同类型的参数时,PowerShell 会隐式地将字符串转换为参数目标类型。 高级函数执行参数值的区域性固定分析。

相比之下,在编译的 cmdlet 的参数绑定期间会执行区分区域性的转换。

在此示例中,我们将创建一个 cmdlet 和一个采用 [datetime] 参数的脚本函数。 当前区域性更改为使用德语设置。 德语格式的日期将传递给参数。

# Create a cmdlet that accepts a [datetime] argument.
Add-Type @'
  using System;
  using System.Management.Automation;
  [Cmdlet("Get", "Date_Cmdlet")]
  public class GetFooCmdlet : Cmdlet {

    [Parameter(Position=0)]
    public DateTime Date { get; set; }

    protected override void ProcessRecord() {
      WriteObject(Date);
    }
  }
'@ -PassThru | % Assembly | Import-Module

[cultureinfo]::CurrentCulture = 'de-DE'
$dateStr = '19-06-2018'

Get-Date_Cmdlet $dateStr
Dienstag, 19. Juni 2018 00:00:00

如上所示,cmdlet 使用区分区域性分析来转换字符串。

# Define an equivalent function.
function Get-Date_Func {
  param(
    [DateTime] $Date
  )
  process {
    $Date
  }
}

[cultureinfo]::CurrentCulture = 'de-DE'

# This German-format date string doesn't work with the invariant culture.
# E.g., [datetime] '19-06-2018' breaks.
$dateStr = '19-06-2018'

Get-Date_Func $dateStr

高级函数使用区域性固定分析,这会导致以下错误。

Get-Date_Func: Cannot process argument transformation on parameter 'Date'.
Cannot convert value "19-06-2018" to type "System.DateTime". Error:
"String '19-06-2018' was not recognized as a valid DateTime."

静态参数

静态参数是函数中始终可用的参数。 PowerShell cmdlet 和脚本中的大多数参数都是静态参数。

以下示例演示具有以下特征的 ComputerName 参数的声明:

  • 它是强制性的(必需)。
  • 它从管道获取输入。
  • 它接受字符串数组作为输入。
param(
    [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
    [string[]]$ComputerName
)

开关参数

开关参数是不使用参数值的参数。 相反,它们通过存在或不存在来传达布尔真或假值,因此,当存在开关参数时,它具有 true 值;当不存在时,它具有 false 值。

例如,Get-ChildItemRecurse 参数是开关参数。

若要在函数中创建 switch 参数,请在参数定义中指定 switch 类型。

例如,函数可以选择以字节数组的形式输出数据:

param([switch]$AsByteArray)

开关参数易于使用,并且优于布尔参数,后者对于 PowerShell 来说语法不太自然。

例如,若要使用开关参数,用户需在命令中键入该参数。

-IncludeAll

若要使用布尔参数,用户需键入参数和布尔值。

-IncludeAll $true

创建开关参数时,请仔细选择参数名称。 确保参数名称向用户传达了参数的效果。 避免含糊不清的用词,例如筛选器最大值,它们可能暗示需要一个值。

开关参数设计注意事项

  • 不应为开关参数指定默认值。 它们应该始终默认为 false。

  • 默认情况下,开关参数不包括在位置参数中。 即使其他参数是隐式位置的,开关参数也不是。 可以在参数属性中覆盖它,但这会让用户感到困惑。

  • 应设计开关参数,以便设置它们将命令从默认行为移动到不太常见或更复杂的模式。 命令最简单的行为应该是不需要使用开关参数的默认行为。

  • 开关参数不应该是强制性的。 仅当需要区分参数集时,才需要强制使用开关参数。

  • 可以使用 -MySwitch:$boolValue 并使用 $params = @{ MySwitch = $boolValue } 散列传递来显式设置布尔值开关。

  • 开关参数的类型为 SwitchParameter,它会隐式转换为布尔值。 参数变量可以直接在条件表达式中使用。 例如:

    if ($MySwitch) { ... }

    无需编写 if ($MySwitch.IsPresent) { ... }

动态参数

动态参数是 cmdlet、函数或脚本的参数,仅在特定条件下可用。

例如,多个提供程序 cmdlet 具有仅当在提供程序驱动器中或在提供程序驱动器的特定路径中使用该 cmdlet 时才可用的参数。 例如,Encoding 参数仅当在文件系统驱动器中使用时才在 Add-ContentGet-ContentSet-Content cmdlet 上可用。

还可以创建仅当函数命令中使用另一个参数或另一个参数具有特定值时才出现的参数。

动态参数可能很有用,但仅在必要时使用它们,因为用户很难发现它们。 若要查找动态参数,用户必须位于提供程序路径中,使用 Get-Command cmdlet 的 ArgumentList 参数,或使用 Get-HelpPath 参数。

若要为函数或脚本创建动态参数,请使用 DynamicParam 关键字。

语法如下:

dynamicparam {<statement-list>}

在语句列表中,使用 if 语句指定参数在函数中可用的条件。

以下示例显示了一个具有名为 NamePath 的标准参数以及名为 KeyCount 的可选动态参数的函数。 KeyCount 参数位于 ByRegistryPath 参数集中,类型为 Int32。 仅当 Path 参数的值以 HKLM: 开头时,Get-Sample 函数中才提供 KeyCount 参数,指示它在 HKEY_LOCAL_MACHINE 注册表驱动器中使用。

function Get-Sample {
  [CmdletBinding()]
  param([string]$Name, [string]$Path)

  DynamicParam
  {
    if ($Path.StartsWith("HKLM:"))
    {
      $parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
          ParameterSetName = "ByRegistryPath"
          Mandatory = $false
      }

      $attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
      $attributeCollection.Add($parameterAttribute)

      $dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
        'KeyCount', [Int32], $attributeCollection
      )

      $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
      $paramDictionary.Add('KeyCount', $dynParam1)
      return $paramDictionary
    }
  }
}

有关详细信息,请参阅 RuntimeDefinedParameter 类型的文档。

参数的属性

本部分介绍可添加到函数参数的属性。

所有属性都是可选的。 但是,如果省略 CmdletBinding 属性,则要被识别为高级函数,该函数必须包含 Parameter 属性。

可以在每个参数声明中添加一个或多个属性。 可以添加到参数声明中的属性数量没有限制。

参数属性

Parameter 属性用于声明函数参数的属性。

Parameter 属性是可选的,如果函数的参数都不需要属性,则可以将其省略。 但是,若要被识别为高级函数,而不是简单函数,函数必须具有 CmdletBinding 属性或 Parameter 属性,或同时具有这两者。

Parameter 属性具有定义参数特征的参数,例如参数是强制的还是可选的。

使用以下语法声明 Parameter 属性、参数和参数值。 括住参数及其值的括号必须跟在 Parameter 后面,中间不能有空格。

param(
    [Parameter(Argument=value)]
    $ParameterName
)

使用逗号分隔括号中的参数。 使用以下语法声明 Parameter 属性的两个参数。

param(
    [Parameter(Argument1=value1, Argument2=value2)]
    $ParameterName
)

Parameter 属性中省略时,Parameter 属性的布尔参数类型默认为 False。 将参数值设置为 $true 或仅按名称列出参数。 例如,以下 Parameter 属性是等效的。

param(
    [Parameter(Mandatory=$true)]
)

# Boolean arguments can be defined using this shorthand syntax

param(
    [Parameter(Mandatory)]
)

如果使用不带参数的 Parameter 属性,作为使用 CmdletBinding 属性的替代方法,则仍需要在属性名称后面加上括号。

param(
    [Parameter()]
    $ParameterName
)

强制参数

Mandatory 参数指示参数是必需的。 如果未指定此参数,则参数是可选的。

以下示例声明 ComputerName 参数。 它使用 Mandatory 参数使参数成为强制参数。

param(
    [Parameter(Mandatory)]
    [string[]]$ComputerName
)

Position 参数

Position 参数确定在命令中使用参数时是否需要参数名称。 当参数声明包含 Position 参数时,可以省略参数名称,并且 PowerShell 通过未命名参数值在命令中未命名参数值列表中的位置或顺序来标识未命名参数值。

如果未指定 Position 参数,则每当在命令中使用参数时,参数名称或参数名称别名或缩写都必须位于参数值之前。

默认情况下,所有函数参数都是位置参数。 PowerShell 按照函数中声明参数的顺序为参数分配位置编号。 若要禁用此功能,请将 CmdletBinding 属性的 PositionalBinding 参数的值设置为 $FalsePosition 参数优先于CmdletBinding 属性的 PositionalBinding 参数的值。 有关详细信息,请参阅 about_Functions_CmdletBindingAttribute 中的 PositionalBinding

Position 参数的值指定为整数。 位置值 0 表示命令中的第一个位置,位置值 1 表示命令中的第二个位置,以此类推。

如果函数没有位置参数,PowerShell 会根据声明参数的顺序为每个参数分配位置。 但是,最佳做法不依赖于此分配。 如果希望参数是位置参数,请使用 Position 参数。

以下示例声明 ComputerName 参数。 它使用值为 0Position 参数。 因此,从命令中省略 -ComputerName 时,其值必须是命令中的第一个或仅未命名的参数值。

param(
    [Parameter(Position=0)]
    [string[]]$ComputerName
)

ParameterSetName 参数

ParameterSetName 参数指定参数所属的参数集。 如果未指定任何参数集,则参数属于函数定义的所有参数集。 为了保持唯一,每个参数集必须至少有一个不属于任何其他参数集的参数。

注意

对于 cmdlet 或函数,参数集的限制为 32 个。

以下示例在 Computer 参数集中声明一个 ComputerName 参数,在 User 参数集中声明一个 UserName 参数,并在两个参数集中都声明一个 Summary 参数。

param(
    [Parameter(Mandatory, ParameterSetName="Computer")]
    [string[]]$ComputerName,

    [Parameter(Mandatory, ParameterSetName="User")]
    [string[]]$UserName,

    [Parameter()]
    [switch]$Summary
)

每个参数中只能指定一个 ParameterSetName 值,每个 Parameter 属性中只能指定一个 ParameterSetName 参数。 若要在多个参数集中包括参数,请添加其他 Parameter 属性。

以下示例将 Summary 参数显式添加到 ComputerUser 参数集。 Summary 参数在 Computer 参数集中是可选参数,在 User 参数集中是强制参数。

param(
    [Parameter(Mandatory, ParameterSetName="Computer")]
    [string[]]$ComputerName,

    [Parameter(Mandatory, ParameterSetName="User")]
    [string[]]$UserName,

    [Parameter(ParameterSetName="Computer")]
    [Parameter(Mandatory, ParameterSetName="User")]
    [switch]$Summary
)

有关参数集的详细信息,请参阅关于参数集

ValueFromPipeline 参数

ValueFromPipeline 参数指示参数接受来自管道对象的输入。 如果函数接受整个对象,而不仅仅是对象的属性,请指定此参数。

以下示例声明一个必需的 ComputerName 参数,并接受从管道传递给函数的对象。

param(
    [Parameter(Mandatory, ValueFromPipeline)]
    [string[]]$ComputerName
)

ValueFromPipelineByPropertyName 参数

ValueFromPipelineByPropertyName 参数指示参数接受管道对象的属性的输入。 对象属性必须与参数具有相同的名称或别名。

例如,如果函数具有 ComputerName 参数,并且管道对象具有 ComputerName 属性,则会将 ComputerName 属性的值分配给函数的 ComputerName 参数。

以下示例声明一个 ComputerName 参数,该参数是必需的,并接受对象 ComputerName 属性的输入,该属性通过管道传递给函数。

param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
    [string[]]$ComputerName
)

请考虑使用此参数的函数实施:

function Test-ValueFromPipelineByPropertyName{
  param(
      [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
      [string[]]$ComputerName
  )
  Write-Output -InputObject "Saw that ComputerName was '$ComputerName'"
}

然后,使用 ComputerName 属性通过管道传递对象的演示如下:

[pscustomobject]@{ ComputerName = "HelloWorld" } |
    Test-ValueFromPipelineByPropertyName
Saw that ComputerName was 'HelloWorld'

注意

接受管道输入 (by Value) 或 (by PropertyName) 的类型化参数允许对参数使用延迟绑定脚本块。

延迟绑定脚本块在 ParameterBinding 期间自动运行。 结果绑定到参数。 延迟绑定不适用于定义为 ScriptBlock 类型 ScriptBlockSystem.Object 的参数。 脚本块通过 传递,无需调用 。 有关 delay-bind 脚本块的详细信息,请参阅 about_Script_Blocks

ValueFromRemainingArguments 参数

ValueFromRemainingArguments 参数指示参数接受未分配给函数的其他参数的命令中的所有参数值。

以下示例声明了一个必需的 Value 参数和一个接受提交给函数的所有剩余参数值的 Remaining 参数。

function Test-Remainder {
    param(
        [Parameter(Mandatory, Position=0)]
        [string]$Value,

        [Parameter(Position=1, ValueFromRemainingArguments)]
        [string[]]$Remaining
    )

    "Found $($Remaining.Count) elements"

    for ($i = 0; $i -lt $Remaining.Count; $i++) {
        "${i}: $($Remaining[$i])"
    }
}
Test-Remainder first one,two
Found 2 elements
0: one
1: two

HelpMessage 参数

HelpMessage 参数指定一个字符串,其中包含参数或其值的简要说明。 如果运行不带强制参数的命令,PowerShell 会提示输入。 若要查看帮助消息,请在提示时键入 !? 并按 Enter

以下示例声明强制 ComputerName 参数和说明预期参数值的帮助消息。

param(
    [Parameter(Mandatory,
    HelpMessage="Enter one or more computer names separated by commas.")]
    [string[]]$ComputerName
)

示例输出:

cmdlet  at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
ComputerName[0]: !?
Enter one or more computer names separated by commas.
ComputerName[0]: localhost
ComputerName[1]:

如果函数没有基于注释的帮助,则会在 Get-Help -Full 输出中显示此消息。

此参数对可选参数没有影响。

Alias 属性

Alias 属性为参数建立备用名称。 可以分配给参数的别名数没有限制。

下面的示例演示了一个参数声明,该声明将 CNMachineName 别名添加到强制 ComputerName 参数。

param(
    [Parameter(Mandatory)]
    [Alias("CN","MachineName")]
    [string[]]$ComputerName
)

Credential 属性

Credential 属性用于指示参数接受凭据。 以下示例演示使用 Credential 属性的参数声明。

param(
    [Parameter()]
    [System.Management.Automation.Credential()]
    [PSCredential]$Credential
)

Experimental 属性

使用 Experimental 属性将某些代码声明为试验性代码。 有关属性的完整说明,请参阅 about_Experimental_Features

PSDefaultValue 属性

PSDefaultValue 指定脚本中命令参数的默认值。 此信息由 Get-Help cmdlet 显示。 若要查看默认值信息,该函数必须包含基于注释的帮助。 例如:

<#
    .SYNOPSIS
     This is a test script that has a parameter with a default value.
#>
function TestDefaultValue {
    param(
        [PSDefaultValue(Help='Current directory')]
        [string]$Name = $PWD.Path
    )

    $Name
}

使用 Get-Help 查看默认值信息。

Get-Help TestDefaultValue -Parameter name
-Name <String>

    Required?                    false
    Position?                    1
    Default value                Current directory
    Accept pipeline input?       false
    Accept wildcard characters?  false

PSDefaultValue 属性参数

PSDefaultValue 属性具有两个参数:

  • Help - 描述默认值的字符串。 此信息由 Get-Help cmdlet 显示。
  • Value - 参数的默认值。

这两个参数都是可选的。 如果未指定任何参数,则 Get-Help 将显示分配给该参数的值。

PSTypeName 属性

不能在类型声明中使用扩展类型名称。 PSTypeName* 属性允许将参数的类型限制为扩展类型。

在此示例中,Test-Connection cmdlet 返回扩展类型。 可以使用 PSTypeName 属性将参数的类型限制为扩展类型。

function TestType {
    param(
        [PSTypeName('Microsoft.PowerShell.Commands.TestConnectionCommand+PingMtuStatus')]
        [psobject]$MtuStatus
    )

    $MtuStatus
}

$mtu = Test-Connection -TargetName bing.com -MtuSize
TestType $mtu

System.Obsolete 属性

使用 System.Obsolete 属性标记不再受支持的参数。 如果要从函数中删除参数,但不想中断使用该函数的现有脚本,这非常有用。

例如,假设有一个具有 NoTypeInformation 开关参数的函数,该参数控制输出中是否包含类型信息。 你希望将该行为设为默认行为并从函数中删除该参数。 但是,你不希望中断使用该函数的现有脚本。 可以将参数标记为已过时,并添加说明更改的消息。

param(
    [System.Obsolete("The NoTypeInformation parameter is obsolete.")]
    [SwitchParameter]$NoTypeInformation
)

SupportsWildcards 属性

SupportsWildcards 属性用于指示参数接受通配符值。 以下示例演示支持通配符值的强制 Path 参数的参数声明。

param(
    [Parameter(Mandatory)]
    [SupportsWildcards()]
    [string[]]$Path
)

使用此属性不会自动启用通配符支持。 cmdlet 开发人员必须实施代码来处理通配符输入。 支持的通配符可能因基础 API 或 PowerShell 提供程序而异。 有关详细信息,请参阅 about_Wildcards

参数补全属性

参数补全属性

通过 ArgumentCompletions 属性,你可以向特定参数添加 Tab 自动补全值。 必须为每个需要 Tab 自动补全的参数定义 ArgumentCompletions 属性。 ArgumentCompletions 属性与 ValidateSet 类似。 当用户在参数名称后按 Tab 时,这两个属性都会接收要显示的值列表。 但是,与 ValidateSet 不同的是,这些值不会经过验证。

此属性是在 PowerShell 6.0 中引入的。

有关详细信息,请参阅 about_Functions_Argument_Completion

ArgumentCompleter 属性

通过 ArgumentCompleter 属性,你可以向特定参数添加 Tab 自动补全值。 必须为每个需要 Tab 补全的参数定义 ArgumentCompleter 属性。 与 DynamicParameters 一样,当用户在参数名称后按 Tab 键时,会在运行时计算可用值。

有关详细信息,请参阅 about_Functions_Argument_Completion

参数和变量验证属性

验证属性指示 PowerShell 测试用户在调用高级函数时提交的参数值。 如果参数值未通过测试,则会生成错误,并且不会调用该函数。 参数验证仅应用于提供的输入,并且不会验证任何其他值(例如默认值)。

还可以使用验证属性来限制用户可以为变量指定的值。

[AllowNull()] [int]$number = 7

验证属性可以应用于任何变量,而不仅仅是参数。 可以为脚本中的任何变量定义验证。

注意

将任何属性与类型化变量一起使用时,最佳做法是先声明属性,然后再声明类型。

如果在属性和变量名称之前声明了带换行符的类型,该类型将被视为其自己的语句。

[string]
[ValidateLength(1,5)] $Text = 'Okay'
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

如果在类型之后声明验证属性,则会在类型转换之前验证所分配的值,这可能会导致意外的验证失败。

[string] [ValidateLength(1,5)]$TicketIDFromInt        = 43
[string] [ValidateLength(1,5)]$TicketIDFromString     = '43'
[ValidateLength(1,5)] [string]$TicketIDAttributeFirst = 43
MetadataError: The attribute cannot be added because variable
TicketIDFromInt with value 43 would no longer be valid.

AllowNull 验证属性

AllowNull 属性允许强制参数的值为 $null。 以下示例声明一个可以具有 null 值的哈希表 ComputerInfo 参数。

param(
    [Parameter(Mandatory)]
    [AllowNull()]
    [hashtable]$ComputerInfo
)

注意

如果类型转换器设置为字符串,则 AllowNull 属性无效,因为字符串类型不接受 null 值。 在这种情况下,可以使用 AllowEmptyString 属性。

AllowEmptyString 验证属性

AllowEmptyString 属性允许强制参数的值为空字符串 ("")。 以下示例声明一个可以具有空字符串值的 ComputerName 参数。

param(
    [Parameter(Mandatory)]
    [AllowEmptyString()]
    [string]$ComputerName
)

AllowEmptyCollection 验证属性

AllowEmptyCollection 属性允许强制参数的值为空集合 @()。 以下示例声明一个可以具有空集合值的 ComputerName 参数。

param(
    [Parameter(Mandatory)]
    [AllowEmptyCollection()]
    [string[]]$ComputerName
)

ValidateCount 验证属性

ValidateCount 属性指定参数接受的最小和最大参数值数。 如果调用函数的命令中的参数值数超出该范围,则 PowerShell 将生成错误。

以下参数声明创建一个采用一到五个参数值的 ComputerName 参数。

param(
    [Parameter(Mandatory)]
    [ValidateCount(1,5)]
    [string[]]$ComputerName
)

ValidateLength 验证属性

ValidateLength 属性指定参数或变量值中的最小和最大字符数。 如果为参数或变量指定的值的长度超出范围,PowerShell 将生成错误。

在以下示例中,每个计算机名必须有一到十个字符。

param(
    [Parameter(Mandatory)]
    [ValidateLength(1,10)]
    [string[]]$ComputerName
)

在以下示例中,变量 $text 的值必须至少为一个字符(长度为 10 个字符)。

[ValidateLength(1,10)] [string] $text = 'valid'

ValidatePattern 验证属性

ValidatePattern 属性指定与参数或变量值进行比较的正则表达式。 如果值与正则表达式模式不匹配,PowerShell 将生成错误。

在下面的示例中,参数值必须包含一个四位数的数字,并且每个数字必须是数字零到 9。

param(
    [Parameter(Mandatory)]
    [ValidatePattern("[0-9]{4}")]
    [string[]]$ComputerName
)

在下面的示例中,变量 $ticketID 的值必须正好是四位数数字,每个数字必须是数字 0 到 9。

[ValidatePattern("^[0-9]{4}$")] [string]$ticketID = 1111

ValidateRange 验证属性

ValidateRange 属性为每个参数或变量值指定数值范围或 ValidateRangeKind 枚举值。 如果任何值超出该范围,PowerShell 将生成错误。

ValidateRangeKind 枚举允许以下值:

  • Positive - 大于 0 的数字。
  • Negative - 小于 0 的数字。
  • NonPositive - 小于或等于零的数字。
  • NonNegative - 大于或等于零的数字。

在以下示例中,Attempts 参数的值必须介于 0 到 10 之间。

param(
    [Parameter(Mandatory)]
    [ValidateRange(0,10)]
    [Int]$Attempts
)

在以下示例中,变量 $number 的值必须介于 0 到 10 之间。

[ValidateRange(0,10)] [int]$number = 5

在以下示例中,变量 $number 的值必须大于 0。

[ValidateRange("Positive")] [int]$number = 1

ValidateScript 验证属性

ValidateScript 属性指定用于验证参数或变量值的脚本。 PowerShell 通过管道将值传递给脚本,并在脚本返回 $false 或脚本引发异常时生成错误。

使用 ValidateScript 属性时,要验证的值将映射到 $_ 变量。 可以使用 $_ 变量来引用脚本中的值。

在以下示例中,EventDate 参数的值必须大于或等于当前日期。

param(
    [Parameter(Mandatory)]
    [ValidateScript({$_ -ge (Get-Date)})]
    [DateTime]$EventDate
)

在以下示例中,变量 $date 的值必须小于或等于当前日期和时间。

[ValidateScript({$_ -le (Get-Date)})] [DateTime]$date = (Get-Date)

注意

如果使用 ValidateScript,则无法将 $null 值传递给参数。 ValidateScript 传递 null 值时,无法验证参数。

重写默认错误消息

从 PowerShell 6 开始,可以使用 ErrorMessage 参数重写指定值无效时生成的默认错误消息。 指定复合格式字符串0 索引组件使用输入值。 1 索引组件使用用于验证输入值的 ScriptBlock

在以下示例中,EventDate 参数的值必须大于或等于当前日期和时间。 如果值无效,错误消息将报告指定的日期和时间太旧。

param(
    [Parameter(Mandatory)]
    [ValidateScript(
        {$_ -ge (Get-Date)},
        ErrorMessage = "{0} isn't a future date. Specify a later date."
    )]
    [DateTime]$EventDate
)

当指定的值为过去的日期时,将返回自定义错误消息。

Cannot validate argument on parameter 'EventDate'. 1/1/1999 12:00:00 AM
isn't a future date. Specify a later date.

可以使用可选的格式字符串组件在字符串中应用进一步的格式。

在以下示例中,EventDate 参数的值必须大于或等于当前日期和时间。 如果值无效,错误消息将报告指定的日期太旧。

param(
    [Parameter(Mandatory)]
    [ValidateScript(
        {$_ -ge (Get-Date).Date},
        ErrorMessage = "{0:d} isn't a future date. Specify a later date."
    )]
    [DateTime]$EventDate
)

当指定的值为过去的日期时,将返回自定义错误消息。

Cannot validate argument on parameter 'EventDate'. 1/1/1999 isn't a future
date. Specify a later date.

ValidateSet 属性

ValidateSet 属性指定参数或变量的一组有效值,并启用 Tab 自动补全。 如果参数或变量值与集中的值不匹配,PowerShell 将生成错误。 在以下示例中,Detail 参数的值只能为 Low、Average 或 High。

param(
    [Parameter(Mandatory)]
    [ValidateSet("Low", "Average", "High")]
    [string[]]$Detail
)

在以下示例中,变量 $flavor 的值必须是 Chocolate、Strawberry 或 Vanilla。

[ValidateSet("Chocolate", "Strawberry", "Vanilla")]
[string]$flavor = "Strawberry"

每次在脚本中分配该变量时,都会进行验证。 例如,以下命令会在运行时导致错误:

param(
    [ValidateSet("hello", "world")]
    [string]$Message
)

$Message = "bye"

此示例会在运行时返回以下错误:

MetadataError: The attribute cannot be added because variable Message with
value bye would no longer be valid.

使用 ValidateSet 还会启用该参数值的 Tab 扩展。 有关详细信息,请参阅 about_Tab_Expansion

使用类的动态 ValidateSet 值

可以使用 Class 在运行时动态生成 ValidateSet 的值。 在以下示例中,变量 $Sound 的有效值是通过名为 SoundNames 的 Class 生成的,该 Class 检查三个文件系统路径中是否有可用的声音文件:

Class SoundNames : System.Management.Automation.IValidateSetValuesGenerator {
    [string[]] GetValidValues() {
        $SoundPaths = '/System/Library/Sounds/',
            '/Library/Sounds','~/Library/Sounds'
        $SoundNames = ForEach ($SoundPath in $SoundPaths) {
            If (Test-Path $SoundPath) {
                (Get-ChildItem $SoundPath).BaseName
            }
        }
        return [string[]] $SoundNames
    }
}

然后,[SoundNames] 类作为动态 ValidateSet 值实施,如下所示:

param(
    [ValidateSet([SoundNames])]
    [string]$Sound
)

注意

IValidateSetValuesGenerator 类是在 PowerShell 6.0 中引入的

ValidateNotNull 验证属性

ValidateNotNull 属性指定参数值不能为 $null。 当值为 $null 时,PowerShell 将引发异常。

ValidateNotNull 属性设计为在参数为可选且类型未定义或具有无法隐式转换 null 值(如 object)的类型转换器时使用。 如果指定隐式转换 null 值的类型(例如字符串),则即使使用 ValidateNotNull 属性,null 值也会转换为空字符串。 在这种情况下,请使用 ValidateNotNullOrEmpty 属性。

在以下示例中,ID 参数的值不能为 $null

param(
    [Parameter()]
    [ValidateNotNull()]
    $ID
)

ValidateNotNullOrEmpty 验证属性

ValidateNotNullOrEmpty 属性指定分配的值不能为以下任何值:

  • $null
  • 空字符串 ("")
  • 空数组 (@())

如果值无效,PowerShell 会引发异常。

param(
    [Parameter(Mandatory)]
    [ValidateNotNullOrEmpty()]
    [string[]]$UserName
)

ValidateDrive 验证属性

ValidateDrive 属性指定参数值必须表示仅引用允许的驱动器的路径。 如果参数值引用了允许的驱动器,则 PowerShell 将生成错误。 路径的存在(驱动器本身除外)未得到验证。

如果使用相对路径,则当前驱动器必须位于允许的驱动器列表中。

param(
    [ValidateDrive("C", "D", "Variable", "Function")]
    [string]$Path
)

ValidateUserDrive 验证属性

ValidateUserDrive 属性指定参数值必须在 User 驱动器中表示。 如果路径引用其他驱动器,PowerShell 将生成错误。 验证属性仅测试路径的驱动器前缀是否存在。

如果使用相对路径,则当前驱动器必须为 User

function Test-UserDrivePath{
    [OutputType([bool])]
    param(
        [Parameter(Mandatory, Position=0)]
        [ValidateUserDrive()]
        [string]$Path
    )
    $True
}

Test-UserDrivePath -Path C:\
Test-UserDrivePath: Cannot validate argument on parameter 'Path'. The path
argument drive C does not belong to the set of approved drives: User.
Supply a path argument with an approved drive.
Test-UserDrivePath -Path 'User:\A_folder_that_does_not_exist'
Test-UserDrivePath: Cannot validate argument on parameter 'Path'. Cannot
find drive. A drive with the name 'User' does not exist.

可以在 Just Enough Administration (JEA) 会话配置中定义 User 驱动器。 在本示例中,我们将创建 User: 驱动器。

New-PSDrive -Name 'User' -PSProvider FileSystem -Root $env:HOMEPATH
Name           Used (GB)     Free (GB) Provider      Root
----           ---------     --------- --------      ----
User               75.76         24.24 FileSystem    C:\Users\ExampleUser
Test-UserDrivePath -Path 'User:\A_folder_that_does_not_exist'
True

ValidateTrustedData 验证属性

此属性已在 PowerShell 6.1.1 中添加。

目前,该属性由 PowerShell 本身在内部使用,不适合外部使用。

另请参阅