about_Functions_Advanced_Parameters

简短说明

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

详细说明

可以将参数添加到你编写的高级函数,并使用参数属性和参数来限制函数用户使用参数提交的参数值。

使用 CmdletBinding 属性时,PowerShell 会自动添加通用参数。 不能创建使用与通用参数相同的名称的任何参数。 有关详细信息,请参阅 about_CommonParameters

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

参数声明

参数是在函数或脚本块的 param() 语句中声明的变量。 可以单独使用可选 [Parameter()] 属性,也可以与 [Alias()] 属性或任何参数验证属性结合使用。

参数名称遵循变量名称的规则。 参数名称由十进制数字、字母字符和下划线组成。 有关命名规则的完整列表,请参阅 about_Variables

重要

可以定义以十进制数字开头的参数。 不建议使用数字启动参数名称,因为 PowerShell 将其视为作为位置参数传递的字符串值。

请考虑以下示例:

function TestFunction {
    param (
        [switch] $100,
        [string] $200
    )

    "100: $100"
    "200: $200"
}

如果尝试使用参数,PowerShell 会将这些参数解释为作为位置参数传递的字符串。

PS> TestFunction -100 -200 Hello
100: False
200: -100
$args: -200 Hello

输出显示 PowerShell 已将值 -100 绑定到 $200 参数变量。 其余位置值绑定到 $args。 若要解决此问题,可以通过 splatting 传递参数值。

PS> $ht = @{100 = $true; 200 = 'Hello'}
PS> TestFunction @ht
100: True
200: Hello
$args:

有关详细信息,请参阅 about_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
)

交换机参数

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

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

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

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

param([switch]$AsByteArray)

切换参数易于使用,比布尔参数更受欢迎,因为后者在 PowerShell 中的语法较不自然。

例如,若要使用 switch 参数,用户键入命令中的参数。

-IncludeAll

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

-IncludeAll $true

创建开关参数时,请仔细选择参数名称。 请确保参数名称将参数的效果传达给用户。 避免使用模棱两可的术语, 例如 过滤器最大值,这些词可能暗示需要一个值。

开关参数设计注意事项

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

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

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

  • 切换参数不应是必需的。 仅当需要区分参数集时,才需要强制使用 switch 参数。

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

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

    if ($MySwitch) { ... }

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

动态参数

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

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

还可以创建仅在函数命令中使用另一个参数或另一个参数具有特定值时显示的参数。

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

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

语法如下所示:

dynamicparam {<statement-list>}

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

以下示例显示了一个函数,其标准参数名为 NamePath,并具有一个名为 KeyCount的可选动态参数。 KeyCount 参数位于 ByRegistryPath 参数集中,其类型为 Int32。 仅当 Path 参数的值以 Get-Sample开头时,KeyCount 参数才在 HKLM: 函数中可用,这表明它正在 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 属性。

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

参数属性

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

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

参数 属性具有定义参数特征的参数,例如参数是必需参数还是可选参数。

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

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

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

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

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

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

# Boolean arguments can be defined using this shorthand syntax

param(
    [Parameter(Mandatory)]
)

如果使用不带参数的 参数 属性,作为使用 CmdletBinding 属性的替代,属性名称后面的括号仍是必需的。

param(
    [Parameter()]
    $ParameterName
)

强制参数

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

以下示例声明 ComputerName 参数。 它使用 Mandatory 参数以使其成为必需项。

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

Position 参数

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

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

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

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

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

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

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

ParameterSetName 参数

ParameterSetName 参数指定参数所属于的参数集。 如果未指定任何参数集,则参数属于函数定义的所有参数集。 若要唯一,每个参数集必须至少有一个参数不是任何其他参数集的成员。

注意

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

以下示例在 参数集中声明 Computer 参数、 参数集中的 User 参数,以及这两个参数集中的 Summary 参数。

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

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

    [Parameter()]
    [switch]$Summary
)

在每个参数中只能指定一个 ParameterSetName 值,在每个 ParameterSetName 属性中只能指定一个 参数。 若要在多个参数集合中包括一个参数,请增加额外的 参数 属性。

以下示例将 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 期间自动运行。 结果绑定到参数。 延迟绑定不适用于定义为 Type 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 输出中显示此消息。

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

DontShow 参数

DontShow 值通常用于辅助处理无法删除过时参数的命令,以实现向后兼容性。 将 DontShow 设置为 True 后,这个参数将对用户隐藏,以用于选项卡扩展和 IntelliSense。

PowerShell v7(及更高版本)使用 DontShow 隐藏以下过时的参数:

  • ConvertTo-CsvExport-Csv 参数
  • Format-Hex 参数
  • Invoke-RestMethodInvoke-WebRequest 参数

DontShow 参数具有以下副作用:

  • 影响关联参数的所有参数集,即使存在未使用 DontShow 的参数集。
  • 隐藏 Tab 自动补全和 IntelliSense 的常见参数。 DontShow 不隐藏可选通用参数:WhatIf确认UseTransaction

Alias 属性

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

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

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

Credential 属性

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

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

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 属性具有两个参数:

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

这两个参数都是可选的。 如果未指定任何参数,则 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 switch 参数,该参数控制类型信息是否包含在输出中。 你想要使该行为成为默认值,并从函数中删除参数。 但是,你不希望中断使用该函数的现有脚本。 可以将参数标记为已过时,并添加说明更改的消息。

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 属性

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

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

有关详细信息,请参阅 about_Functions_Argument_Completion

ArgumentCompleter 属性

通过 ArgumentCompleter 属性,你可以向特定参数添加 Tab 自动补全值。 必须为每个需要 Tab 自动补全的参数定义 ArgumentCompleter 属性。动态参数一样,当用户在参数名称后按下 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。 以下示例声明一个哈希表 ComputerInfo 参数,该参数可以具有 null 值。

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 的值必须至少为一个字符(长度为 1 个字符),最大长度为 10 个字符。

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

ValidatePattern 验证属性

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

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

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

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

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

ValidateRange 验证属性

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

ValidateRangeKind 枚举允许以下值:

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

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

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

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

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

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

[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 值传递给参数。 当你传递一个 null 值时,ValidateScript 无法验证该参数。

重写默认错误消息

从 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 值

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

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
)

注意

PowerShell 6.0 中引入了 IValidateSetValuesGenerator

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
)

ValidateNotNullOrWhiteSpace 验证属性

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

  • $null
  • 空字符串 (""
  • 空数组 @()
  • 仅包含空格字符的字符串,如制表符、空格、回车符和换行符
  • 包含空或仅包含空格字符的任何字符串的数组

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

param(
    [Parameter(Mandatory)]
    [ValidateNotNullOrWhiteSpace()]
    [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: drive。

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 本身在内部使用,不适用于外部使用。

此属性已在 PowerShell 6.1.1 中添加。

另请参阅