当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

作者:精品下载站 日期:2024-12-14 20:52:02 浏览:17 分类:玩电脑

使用 PowerShell ValidateScript 验证参数 [演练]


创建 PowerShell 函数时,验证参数的输入非常重要。参数验证允许您限制传递给函数的内容。在本文中,您将学习如何在问题成为 PowerShell ValidateScript 验证属性之前发现问题。

使用参数验证,您不仅可以确保函数运行后不会出现问题,而且还可以提高代码的简洁性,因为验证逻辑没有放置在函数体内。

Powershell 中提供了多种高级参数验证属性。但在本文中,您将了解最灵活的参数验证之一:PowerShell ValidateScript 验证。

您将了解它的工作原理,并查看如何使用它的示例。

参数验证(类比)

我正在吃午饭,突然想喝一杯苏打水。我走到汽水机前,从口袋里掏出一张 100 比索的钞票,将其插入钞票投币口。机器立刻吐出来。

然后我注意到,就在投币口上方,写着只接受 20 比索和 50 比索的钞票。我最终没有喝到苏打水,因为我身上只有那张 100 比索的钞票。

这个故事与 PowerShell 参数验证有何关系?让我们来分解一下。

  • 汽水机作为功能
  • 账单就是参数
  • 50 比索和 20 比索钞票是有效参数值
  • ₱100 被拒绝,因为它是错误的参数值
  • 结果机器因为输入错误而没有处理我的请求。因此,我没有苏打水。 ……我也渴了!

上面的汽水机场景只是描述参数验证概念的一种类比。

参数验证逻辑流程

参数验证的概念遵循一个粗略的工作流程。下图显示了参数验证如何工作的概述。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

  1. 该函数通过调用其名称并提供参数值在 PowerShell 中执行
  2. PowerShell 评估提供的值。
  3. 如果验证结果为真,PowerShell 将允许该函数在退出之前继续其进程。
  4. 如果验证结果为 false,PowerShell 将显示错误并且该函数将终止。

演练要求

本文的其余部分不仅仅讨论 PowerShell 函数参数验证,还将提供一些示例,您可以复制并自行尝试。为了跟进,您需要遵循一些事情。

  • 具有以下任何 PowerShell 版本的 Windows 10 计算机:
  • Windows PowerShell 5.1
  • PowerShell 核心 6.2
  • PowerShell Core 7(本文的最新版本是预览版 4)
  • 您选择的脚本编辑器。例如,Notepad++、PowerShell ISE 或 Visual Studio Code。

了解ValidateScript验证属性

ValidateScript 是 PowerShell 3.0 中引入的可在 PowerShell 中使用的参数验证属性之一。它可以添加到函数的参数定义块内,也可以直接在PowerShell控制台中使用。

ValidateScript用于验证您输入的参数值。如果验证结果为$true,则脚本将继续运行。另一方面,如果结果为 $false,该函数将抛出终止错误。

让我们深入看看它是如何工作的。

在函数中使用 ValidateScript

ValidateScript 属性最常见的用途是附加到函数参数。在本部分中,您将创建一个虚拟函数并应用 ValidateScript 参数验证。

虚拟函数将执行以下操作:

  1. 接受金额输入。
  2. 验证输入的金额是否等于接受的值。
  3. 如果验证通过,则运行该流程。
  4. 如果验证失败,则显示错误。

您将在下一节中逐步学习如何构建此函数。启动脚本编辑器并开始编码!

构建函数

首先,创建一个函数并为其命名。这可以是您选择的任何名称。最佳实践是遵循动词-名词命名约定,使您的函数具有描述性。对于本示例,请使用名称 Get-Soda

Function Get-Soda {
    [CmdletBinding()]
    param ()
}

param() 块内,插入您将使用的参数名称,即 Bill

Function Get-Soda {
    [CmdletBinding()]
    param ( 
        $Bill
    )
}

此时,该函数除了接受 Bill 参数的任何值之外,尚未执行任何操作。

确保您已将 Get-Soda 函数复制到 PowerShell 控制台中。将函数导入 PowerShell 会话后,通过运行命令来测试函数:Get-Soda -Bill 100

当您运行 Get-Soda 函数时,您会注意到没有抛出任何错误,并且它什么也不做。这是目前预计的情况。

添加参数验证

也许您不想允许将所有值传递给 Bill 参数。使用本文顶部解释的类比,该函数不应允许 100 比索的钞票。它应该只允许 50 比索和 20 比索的钞票。

通过在 Bill 参数之前插入 [ValidateScript()] 添加 ValidateScript 参数验证。您的函数应该类似于下面的代码。

Function Get-Soda {
    [CmdletBinding()]
    param (
        [ValidateScript()]
        $Bill 
    )
}

[ValidateScript()]块内部,插入验证代码{$_ -eq 20}。此验证代码检查提供给 bill 参数的值是否等于 20。下面的代码片段是代码的样子。

注意:$_ 表示作用域中当前参数的值。在此示例中,$_ 的值是参数 Bill 的值。

Function Get-Soda {
    [CmdletBinding()]
    param (
        [ValidateScript({$_ -eq 20})]
        $Bill
    )
}

现在再次运行此函数,通过运行以下命令来确认参数验证是否正常工作:

PS51> Get-Soda -Bill 20
PS51> Get-Soda -Bill 30

下面您可以看到,当 20 作为值传递时,不会发生任何事情,但当传递 20 以外的任何值时,它会引发错误。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

Get-Soda函数没有抛出错误时,意味着函数执行成功。为了演示这一点,请在函数内添加以下代码,以简单地将消息返回到控制台。

Write-Host "$Bill is an accepted value. Please select your soda."

Get-Soda 函数将如下所示:

Function Get-Soda {
    [CmdletBinding()]
    param (
        [ValidateScript({$_ -eq 20})]
        $Bill 
    )

    Write-Host "$Bill is an accepted value. Please select your soda."
}

现在将一个接受的值(例如 20)传递给 Bill 参数。您应该看到下面的结果。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

显示更有意义的错误消息

相信你现在已经注意到,当参数值没有通过验证时返回的错误消息不是很直观,而且很难看。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

遗憾的是,您对错误的外观无能为力。在发布支持验证错误格式的功能(希望如此)之前,您将不得不使用它。

但是,可以对其进行一点改进,并赋予错误更多含义,这可以使您的用户受益。接下来您将看到如何执行此操作的示例。

使用 Windows PowerShell 添加自定义验证错误 (5.1)

扩展 Get-Soda 函数,当值不符合验证时,可以抛出特定的错误消息。为此,您可以在 ValidateScript 块内添加 if/then 构造。

创建一个简单的 if/then 结构,如下例所示。在此示例中,如果 Bill 参数值不等于 20,它将返回您选择的错误消息(X 无效。有效值为 20。) 。

您可以在下面看到一个示例:

Function Get-Soda {
    [CmdletBinding()]
    param (
        [ValidateScript({
        if ($_ -eq 20) {
            $true
        } else {
            throw "$_ is invalid. Valid value is 20 only."
        }
    })]
    $bill
    )
    process {
        Write-Host "$bill is an accepted value. Please select your soda."
    }
}

下面的屏幕截图显示了正在运行的自定义错误消息。该错误看起来仍然很难看,但这次消息清晰易懂。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

使用 PowerShell Core 添加自定义验证错误 (6+)

从 PowerShell Core 6 开始,已经内置了向 ValidateScript 参数验证添加自定义错误消息的功能。我们将其称为ErrorMessage 技术

在下面修改后的 Get-Soda 函数代码中,[ValidateScript()] 块现在包含一个 ErrorMessage 属性,可以在以下位置使用 ErrorMessage 属性:代码>抛出。现在,您可以使用 {0} 来代替 $_ 变量,它代表传递的参数值。

Function Get-Soda {
    [CmdletBinding()]
    param (
        [ValidateScript({
            $_ -eq 20            
        },
        ErrorMessage = "{0} is invalid. Valid value is 20 only."
        )]
        $Bill
	)
    Write-Host "$Bill is an accepted value. Please select your soda."
}

下面的屏幕截图显示预期输出与使用 if-else 和 throw 技术完全相同。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

PowerShell ValidateScript 用法示例

这些是一些可以应用 ValidateScript 的实际用例场景。查看并测试这些示例,然后尝试使用您在上一节中学到的技术自行改进错误消息。

日期参数验证

此代码片段是一个接受开始日期和结束日期的函数。它会验证输入的日期不是将来的日期且不早于 90 天。

<#
    Dummy function to search logs.
    Accepts the following parameters.

        * startDate
            - date must not be older than 90 days.
            - date must not be in the future.
        * endDate
            - date must not be older than 90 days.
            - date must not be in the future.
#>
Function Search-Log {
    [CmdletBinding()]
    param (
        [parameter(Mandatory)]
        [ValidateScript({
            ($_ -gt (Get-Date -Hour 0 -Minute 0 -Second 0).AddDays(-90) -and $_ -le (Get-Date))
        })]
        [datetime]$startDate,


        [parameter(Mandatory)]
        [ValidateScript({
            ($_ -gt (Get-Date -Hour 0 -Minute 0 -Second 0).AddDays(-90) -and $_ -le (Get-Date))
        })]
        [datetime]$endDate
    )

    process {
        Write-Host "I will search the logs between [$startDate] and [$endDate"]
    } 
}

使用这些命令测试该功能。您可以指定自己的 startDateendDate

#TEST: Dates are valid
$startDate = (Get-Date).AddDays(-90) #Today - 90 days
$endDate = (Get-Date) # Today
search-log -startDate $startDate -endDate $endDate

下面的示例输出是输入有效日期值时的输出。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

现在使用超过 90 天的 startDate 再次测试它。然后确认是否显示错误消息。

Windows 进程参数验证

下一个代码片段是一个接受进程名称的函数。它确认进程正在内存中运行,然后根据验证结果杀死该进程的所有正在运行的实例或退出。

<#
    A function to kill all instances of a process.
    Usage: Kill-Process -name <process name>
    Example: Kill-Process -name notepad
#>

Function Kill-Process {
    [CmdletBinding()]
    param (
        [parameter(Mandatory)]
        [ValidateScript(
            {
                if (Get-Process -Name $_) {
                    $true
                }
                else {
                    throw "A process with name $_ is not found."
                }
            }
        )]
        [string]$Name
    )
    process {
        Write-Host "Killing Process: $Name"
        Stop-Process -Name $Name -Force
    }
}

使用以下命令进行测试:Kill-Process -Name

下面的示例输出假设您正在使用名为 notepad 的进程进行测试。

  • 第一个命令成功运行,因为它发现 notepad 进程正在运行并继续终止它。
  • 第二个命令失败,因为 notepad 不再运行,并且该函数以您创建的自定义错误消息结束。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

通过另一个参数值验证参数

现在您应该了解在函数中使用 ValidateScript 的价值。但有一个限制值得一提。 ValidateScript的范围仅在使用的参数内。这意味着一个参数不能使用其他参数的值。

作为解决方法,可以通过访问 $PSBoundParameters 自动变量来完成跨参数值检查。

也许您有一个名为 Send-Spam 的函数。该函数有三个参数:

  1. 发件人 - 发件人的电子邮件地址。 (例如[电子邮件受保护])。不是强制性的。
  2. To - 收件人的电子邮件地址。 (例如[电子邮件受保护])。不是强制性的。
  3. SendEmail - 不需要值的开关参数。但如果使用,则需要 FromTo 参数值。

如果使用 SendEmail 开关,将运行验证代码以确认使用了 FromTo 参数。然后它将返回True值。另一方面,如果 FromTo 未使用,该函数将抛出错误并退出。

将以下代码复制并粘贴到您的 PowerShell 会话中。

<#
    Dummy function to send spam
    Accepts the parameters
        
        From
            - sender email address
            - cannot be null or empty
        To
            - recipient email address
            - cannot be null or empty
        SendEmail
            - a switch (on/off) parameter.
            - it will validate if 'To' and 'From' values are present.

    Usage: Send-Spam -From [email  -To [email  -SendEmail
#>

Function Send-Spam {
    [CmdletBinding()]
    param (
        [parameter()]
        [ValidateNotNullOrEmpty()] #Ensure From is not equal to $null or ""
        [mailaddress]$From,

        [parameter()]
        [ValidateNotNullOrEmpty()] #Ensure To is not equal to $null or ""
        [mailaddress]$To,

        [parameter()]
        [ValidateScript(
            {
                # Check if the From and To parameters are specified

                if ($PSBoundParameters.Keys -contains 'From' -AND
                    $PSBoundParameters.Keys -contains 'To') {
                        $true
                }
                else {
                    throw "From and To parameters are required when using SendEmail"
                }
            }
        )]
        [switch]$SendEmail
    )

    process {
        Write-Host "From: $From" -ForegroundColor Yellow
        Write-Host "To: $To" -ForegroundColor Cyan
        if ($SendEmail) {
            Write-Host "Sending Spam from '$From' to '$To'" -ForegroundColor Green
        }        
    }
}

下面显示的命令将导致验证成功。因为 FromTo 参数与 SendEmail 开关一起使用。

PS51> Send-Spam -From [email  -To [email  -SendEmail

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

现在,不使用 FromTo 参数进行测试。这应该会导致错误,因为验证脚本将失败。请参阅下面的示例结果。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

在控制台中使用 ValidateScript

尽管 ValidateScript 属性最常见的用途是用于验证函数参数,但它也可以直接从 PowerShell 控制台使用。 ValidateScript 对于测试您的验证代码非常有用,甚至在将其合并到脚本或函数之前也是如此。

以下是在函数外部使用 ValidateScript 的一些示例。

验证整数值

下面的示例验证给定的整数值是否大于 5。

[ValidateScript({$_ -gt 5})]$i=4

运行上述代码后,预期结果失败,因为给定值为 4,小于 5。下面的示例屏幕截图就是您期望看到的内容。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

验证日期值

下面的下一个示例代码显示如何验证给定日期是否晚于或等于当前日期。

[DateTime][ValidateScript({$_ -ge (Get-Date)})]$date = (Get-Date)
[DateTime][ValidateScript({$_ -ge (Get-Date)})]$date = (Get-Date).AddHours(-1)

运行上述代码片段中的第一行代码后,预期结果已通过 (True),因为提供的 DateTime 值相同或稍大几秒。

第二行代码将产生失败的结果,因为 DateTime 值比当前时间少一小时。请参阅下面的屏幕截图以获取示例输出。

[玩转系统] 使用 PowerShell ValidateScript 验证参数 [演练]

概括

在本文中,您了解了参数验证是什么以及如何使用 ValidateScript 参数验证属性。

您还了解了如何扩展其功能以显示更具描述性的错误消息。在遵循示例时,您已经体验了成功和失败验证的结果。

您现在应该了解 ValidateScript 在跨参数引用方面的限制,以及如何利用 $PSBoundParameters 自动变量来解决该限制。

我希望您在本文中学到了足够的知识,可以在您的 PowerShell 工具制作之旅中应用!

进一步阅读

  • Powershell功能介绍
  • 了解和构建 PowerShell 模块
  • ValidateScript 验证属性
  • 关于投掷

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯