powershell 验证脚本和操作顺序

1l5u6lss  于 2023-02-19  发布在  Shell
关注(0)|答案(1)|浏览(118)

我不明白为什么ValidateScript直到最后才出错。

param (
    [Parameter(
        Mandatory = $true,
        HelpMessage = "Specifies the email address that will manage the share drive to be created.")]
        [ValidateScript({
            if ($_.host -eq "domain.com") {
                return $true
            }
            else {
                Throw [System.Management.Automation.ValidationMetadataException] "Enter an email address ending with @domain.com"
            }
        })][Net.Mail.MailAddress]$EmailAddress,
    
    [Parameter(
        Mandatory = $true,
        HelpMessage = "Specifies the name of the share drive name to be created. Enter a shared drive name like prgm- and at least 2 letters. Example prgm-hi")]
    [ValidateScript({
            if ($_ -like "prgm-??*") {
                return $true
            }
            else {
                Throw [System.Management.Automation.ValidationMetadataException] "Enter a shared drive name like prgm- and at least 2 letters. Example prgm-hi"
            }
        })][string]$SharedDriveName
)

在上面的代码片段示例中,如果脚本运行,则用户将跳过emailaddress变量(如果它是错误的),然后在所有变量都被回答后返回错误。
我不明白如何让脚本停止的权利,因为有人作出了一个坏的条目。
我想,我将不得不使用验证脚本以外的东西,但我不确定是什么?

snvhrwxg

snvhrwxg1#

可能令人惊讶的是,当PowerShell自动提示输入缺少的强制参数的值时(自PowerShell 7.3.2起编写):

  • 它在每个提示符 * 之后强制参数数据类型 *。
  • 仅在回答了所有提示后*才执行 * 验证 *-基于ValidateScript()等属性。

这造成了一种尴尬的交互体验,因为作为一个用户,你不会知道你的任何输入是否有效,直到 * 所有 * 输入都被提供。
我无法说明设计意图--此评估顺序的一个 * 可能 * 原因是允许验证脚本块也考虑 * 其他 * 参数值;但是,* 实际上 * 您 * 不能 * 引用[ValidateScript()]脚本块中的其他参数。
总的来说,自动提示机制有一些基本的限制-参见GitHub issue #7093

    • 解决方法**:

你可以**把提示和验证移到你的函数的 * body * 中,在那里你可以控制执行流程--显然,这需要额外的工作:

param (
  [Parameter(
    # Do NOT make the parameter mandatory, so that it can be prompted for
    # in the function body, but DO define a HelpMessage.
    HelpMessage = "Specify the email address that will manage the share drive to be created (must end in @sonos.com)"
  )]
  [ValidateScript({
      if ($_.host -eq 'sonos.com') {
        return $true
      }
      else {
        Throw "Enter an email address ending with @sonos.com"
      }
  })]
  [Net.Mail.MailAddress] $EmailAddress,
    
  [Parameter(
    # Do NOT make the parameter mandatory, so that it can be prompted for
    # in the function body, but DO define a HelpMessage.
    HelpMessage = "Specify the name of the share drive name to be created. Enter a shared drive name like prgm- and at least 2 letters. Example prgm-hi"
  )]
  [ValidateScript({
      if ($_ -like "prgm-??*") {
        return $true
      }
      else {
        Throw "Enter a shared drive name like prgm- and at least 2 letters. Example prgm-hi"
      }
  })]
  [string]$SharedDriveName
)

# If no values were provided any of the conceptually mandatory parameters,
# prompt for and validate them now.
# Infer which parameters are conceptually mandatory from the presence of a 
# .HelpMessage property.
$MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object {
  # See if there's a .HelpMessage property value and, if so,
  # check if the parameter hasn't already been bound.
  $helpMessage = $_.Value.Attributes.Where({ $_ -is [Parameter] }).HelpMessage
  if ($helpMessage -and -not $PSBoundParameters.ContainsKey($_.Key)) {
    # Prompt now and validate right away, which happens implicitly when
    # the parameter variable is assigned to.
    while ($true) {
      try {
        Set-Variable -Name $_.Key -Value (Read-Host $helpMessage)
        break # Getting here means that validation succeeded -> exit loop.
      }
      catch { 
        # Validation failed: write the error message as a warning, and keep prompting.
        Write-Warning "$_"
      }
    }
  }
}

# ... all required arguments are now present and validated.

注:

  • 这种方法的好处是,您可以 * 保持提示 *,直到收到有效的输入(或者用户使用Ctrl-C中止)。

相关问题