[玩转系统] PowerShell ValidateSet:从列表中选择
作者:精品下载站 日期:2024-12-14 20:52:19 浏览:13 分类:玩电脑
PowerShell ValidateSet:从列表中选择
当您编写 PowerShell 脚本或函数时,您通常希望通过参数接受用户输入。如果您不限制这些参数接受的值,则可以保证会出现提供不适当值的情况。在本文中,了解如何使用 PowerShell ValidateSet 参数验证属性将这些值限制为仅您定义的值。
编写 PowerShell 脚本或函数时,您可以使用许多不同的验证属性来检查提供给参数的值是否可接受,如果不可接受,则提醒用户。
本文重点介绍 ValidateSet 验证属性。您将了解 ValidateSet 的作用、为什么要在代码中使用 ValidateSet 以及如何操作。您还将了解 ValidateSet 启用的制表符完成功能,该功能将帮助您的代码用户提供有效的参数值。
PowerShell ValidateSet:简要概述
ValidateSet 是一个参数属性,允许您定义一组仅接受作为该参数值的元素。
例如,也许您有一个定义为与 Active Directory 域控制器一起使用的脚本。该脚本有一个参数指定域控制器的名称。将可接受值列表限制为域控制器的实际名称是否有意义?当您事先知道脚本需要什么值时,用户没有理由能够使用“foobar”作为值。 ValidateSet 为您提供了这种功能。
要求
本文将是一个学习演练。如果您打算跟随,您将需要以下内容:
- Visual Studio Code 或任何其他代码编辑器。我将使用 Visual Studio Code。
- 本文中的大部分代码至少使用 PowerShell 5.1。有一个部分需要 PowerShell 6.1 或更高版本,当我们讨论它时我会指出这一点
本文所有代码均已在以下环境中测试:
Windows 7 SP15.1、核心6.2
Windows 10 19035.1、核心6.2
Linux Mint 19.2核心6.2
为了帮助解释有关 ValidateSet 的概念,您将构建一个名为 Get-PlanetSize.ps1 的小脚本。该脚本返回有关太阳系中行星大小的信息。
您将从一个简单的脚本开始,逐步提高其处理最终用户输入的能力,并使他们能够轻松发现其可能的参数值。
入门
首先,首先将下面的 PowerShell 代码复制并粘贴到您喜欢的文本编辑器中,并将其另存为 Get-PlanetSize.ps1。
$planets = [ordered]@{
'Mercury' = 4879
'Venus' = 12104
'Earth' = 12756
'Mars' = 6805
'Jupiter' = 142984
'Saturn' = 120536
'Uranus' = 51118
'Neptune' = 49528
'Pluto' = 2306
}
$planets.keys | Foreach-Object {
$output = "The diameter of planet {0} is {1} km" -f $_, $planets[$_]
Write-Output $output
}
从 PowerShell 提示符运行该脚本,您应该得到以下信息:
PS51> .\Get-PlanetSize.ps1
The diameter of planet Mercury is 4879 km
The diameter of planet Venus is 12104 km
The diameter of planet Earth is 12756 km
The diameter of planet Mars is 6805 km
The diameter of planet Jupiter is 142984 km
The diameter of planet Saturn is 120536 km
The diameter of planet Uranus is 51118 km
The diameter of planet Neptune is 49528 km
The diameter of planet Pluto is 2306 km
信息丰富但不太灵活;即使您只想要火星的信息,也会返回每个行星的信息。
也许您希望能够指定单个行星而不是返回所有行星。您可以通过引入一个参数来做到这一点。接下来让我们看看如何实现这一目标。
使用参数接受输入
要允许脚本接受参数,请将 Param()
块添加到脚本顶部。调用参数Planet
。合适的 Param()
块如下所示。
在下面的示例中,行[Parameter(Mandatory)]
确保行星名称始终提供给脚本。如果缺少,则脚本将提示输入一个。
Param(
[Parameter(Mandatory)]
$Planet
)
将此 Planet
参数合并到脚本中的最简单方法是更改行 $planets.keys | Foreach-Object {
到 $Planet | Foreach-对象{
.现在,您不再依赖于之前静态定义的哈希表,而是读取 Planet
参数的值。
现在,如果您运行脚本并使用 Planet
参数指定行星,您将只能看到有关该特定行星的信息。
PS51> .\Get-PlanetSize.ps1 -Planet Mars
The diameter of planet Mars is 6805 km
出色的。剧本完成了吗?也许不会。
选项太开放
如果您尝试使用 Get-PlanetSize.ps1 查找行星 Barsoom 的直径,会发生什么?
PS51> .\Get-PlanetSize.ps1 -Planet Barsoom
The diameter of planet Barsoom is km
嗯,这是不对的。 Barsoom 不在行星列表中,但脚本仍然运行。我们该如何解决这个问题?
这里的问题是脚本接受任何输入并使用它,无论它是否是有效值。该脚本需要一种方法来限制 Planet
参数接受哪些值。输入ValidateSet!
确保仅使用某些值
ValidateSet 列表是以逗号分隔的字符串值列表,用单引号或双引号括起来。向脚本或函数参数添加 ValidateSet 属性包括向 Param()
块添加一行文本,如下所示。将 Get-PlanetSize.ps1 副本中的 Param()
块替换为下面的块并保存文件。
Param(
[Parameter(Mandatory)]
[ValidateSet("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune","Pluto")]
$Planet
)
尝试使用 Barsoom 作为 Planet
参数再次运行脚本。现在返回了一条有用的错误消息。该消息具体说明了问题所在,甚至提供了参数的可能值列表。
PS51> .\Get-PlanetSize.ps1 -Planet Barsoom
Get-PlanetSize.ps1 : Cannot validate argument on parameter 'Planet'. The argument "Barsoom" does not belong to the set
"Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Pluto" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:1 char:32
.\Get-PlanetSize.ps1 -Planet Barsoom
~~~
CategoryInfo : InvalidData: (:) [Get-PlanetSize.ps1], ParameterBindingValidationException
FullyQualifiedErrorId : ParameterArgumentValidationError,Get-PlanetSize.ps1
使 PowerShell ValidateSet 区分大小写
默认情况下,ValidateSet 属性不区分大小写。这意味着它将允许任何位于允许列表中且具有任何大小写方案的字符串。例如,上面的示例将像接受 mars
一样轻松地接受 Mars
。如有必要,您可以使用 IgnoreCase
选项强制 ValidateSet 区分大小写。
ValidateSet 验证属性中的 IgnoreCase
选项确定提供给参数的值是否与有效值列表完全匹配。默认情况下,IgnoreCase
设置为 $True
(忽略大小写)。如果将此设置为 $False
,则提供 mars 作为 Get-PlanetSize.ps1
的 Planet
参数的值> 将生成错误消息。
您可以通过在有效值列表末尾为其分配一个 $true
值来使用 IgnoreCase
选项,如下所示。
[ValidateSet("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", IgnoreCase = $false)]
现在,当您尝试使用与列表中的值不完全一样的 Planet
值时,验证将会失败。
使用制表符补全
使用 ValidateSet 的另一个好处是它可以为您提供制表符补全功能。这意味着您可以使用 TAB 键循环浏览参数的可能值。这极大地提高了脚本或函数的可用性,尤其是在控制台中。
在下面的示例中,有几点需要注意:
- 显示最后一个值后,制表符完成会循环回到第一个值。
- 这些值按字母顺序显示,即使它们未按字母顺序列在 ValidateSet 中。
- 键入首字母并按 TAB 键会将制表符补全提供的值限制为以该字母开头的值。
您还可以利用 PowerShell 集成脚本环境 (ISE) 中的 ValidateSet 选项卡完成功能,如下面的示例所示。 ISE Intellisense 功能会在一个漂亮的选择框中向您显示可能值的列表。
Intellisense 返回包含您键入的字母的所有值,而不仅仅是以该字母开头的值。
现在我们已经介绍了 Windows 5.1 中的 ValidateSet 验证属性,让我们看一下 PowerShell Core 6.1 中添加的内容,看看是否可以为我们的脚本提供更多验证功能。
了解 PowerShell 6.1 中 ValidateSet 的更改
随着 PowerShell Core 6.1 的到来,ValidateSet 验证属性中添加了两项新功能:
ErrorMessage
属性- 通过访问 System.Management.Automation.IValidateSetValuesGenerator 来使用 ValidateSet 中的类
ErrorMessage 属性
当您向 Get-PlanetSize.ps1 提供不正确的行星名称时生成的默认错误消息很有帮助,但有点冗长:
PS61> .\Get-PlanetSize.ps1 -Planet Barsoom
Get-PlanetSize.ps1 : Cannot validate argument on parameter 'Planet'. The argument "Barsoom" does not belong to the set
"Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Pluto" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.
At line:1 char:32
.\Get-PlanetSize.ps1 -Planet Barsoom
~~~
CategoryInfo : InvalidData: (:) [Get-PlanetSize.ps1], ParameterBindingValidationException
FullyQualifiedErrorId : ParameterArgumentValidationError,Get-PlanetSize.ps1
使用 ValidateSet
验证属性的 ErrorMessage
属性可以设置不同的错误消息,如下面的示例所示。 {0}
自动替换为提交的值,{1}
自动替换为允许值的列表。
Param(
[Parameter(Mandatory)]
[ValidateSet("Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune","Pluto",ErrorMessage="Value '{0}' is invalid. Try one of: '{1}'")]
$Planet
)
替换脚本文件中的 Param()
块并保存。然后再次尝试 Get-PlanetSize.ps1 -Planet Barsoom
。请注意,下面的错误内容要少得多,并且更具描述性。
PS61> .\Get-PlanetSize.ps1 -Planet Barsoom
Get-PlanetSize.ps1 : Cannot validate argument on parameter 'Planet'. Value 'Barsoom' is invalid. Try one of: 'Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Pluto'
At line:1 char:32
.\Get-PlanetSize.ps1 -Planet Barsoom
~~~
CategoryInfo : InvalidData: (:) [Get-PlanetSize.ps1], ParameterBindingValidationException
FullyQualifiedErrorId : ParameterArgumentValidationError,Get-PlanetSize.ps1
接下来,了解一种通过 PowerShell 类定义 ValidateSet 中可接受值的新方法。
PowerShell 类
自定义类型(在 PowerShell 中称为类)自版本 5 起就已可用。随着 PowerShell Core 6.1 的到来,出现了一项新功能,允许使用类来提供 ValidateSet 的值。
使用类可以解决 ValidateSet 的主要限制——它是静态的。也就是说,它作为函数或脚本的一部分嵌入,并且只能通过编辑脚本本身来更改。
与 ValidateSet 配合使用的新功能是能够使用 System.Management.Automation.IValidateSetValuesGenerator 类。我们可以使用继承来将其用作我们自己的类的基础。要使用 ValidateSet
,该类必须基于 System.Management.Automation.IValidateSetValuesGenerator,并且必须实现名为 GetValidValues()
的方法。
GetValues()
方法返回您希望接受的值的列表。将静态行星列表替换为 [Planet]
类的 Param()
块如下所示。这个例子还不能运行。继续阅读以了解如何实现这一点。
Param(
[Parameter(Mandator)]
[ValidateSet([Planet],ErrorMessage="Value '{0}' is invalid. Try one of: {1}")]
$Planet
)
使用类作为 ValidateSet 值列表:一个真实示例
为了演示如何使用 ValidateSet 值列表的类,您将用从 CSV 文本文件加载的列表替换之前使用的静态行星列表。您不再需要在脚本本身内部维护静态值列表!
为类创建数据源
首先,您需要创建一个包含每个有效值的 CSV 文件。为此,请将这组数据复制并粘贴到新的文本文件中,并将其另存为 planets.csv 与 Get-PlanetSize.ps1 脚本位于同一文件夹中。
Planet,Diameter
"Mercury","4879"
"Venus","12104"
"Earth","12756"
"Mars","6805"
"Jupiter","142984"
"Saturn","120536"
"Uranus","51118"
"Neptune","49528"
"Pluto","2306"
将类添加到脚本中
ValidateSet 使用的任何类必须在 ValidateSet 尝试使用它之前已经定义。这意味着 Get-PlanetSize.ps1 的结构将无法正常工作。
[Planet]
类必须在使用之前定义,因此它必须位于脚本的开头。合适的骨架类定义如下所示:
class Planet : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues() {
}
}
在类的 GetValidValues()
方法中,使用 Import-CSV
cmdlet 导入之前创建的文本文件 planets.csv。该文件被导入到一个名为 $planets
的全局变量中,以便稍后在脚本中访问它。
使用 return
语句通过 GetValidValues()
返回行星名称列表。经过这些更改后,类现在应如下所示。
class Planet : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues() {
$Global:planets = Import-CSV -Path planets.csv
return ($Global:planets).Planet
}
}
接下来,从脚本中删除 $planets
哈希表声明,如下所示。由 [Planet]
类填充的全局变量 $planets
包含行星数据。
$planets = [ordered]@{
'Mercury' = 4879
'Venus' = 12104
'Earth' = 12756
'Mars' = 6805
'Jupiter' = 142984
'Saturn' = 120536
'Uranus' = 51118
'Neptune' = 49528
'Pluto' = 2306
}
现在将剩余的原始代码包装在一个函数中,并将其命名为 Get-PlanetDiameter
以将其与脚本的名称区分开来。将脚本开头的 Param()
块放置在函数内。将行星的静态列表替换为对 [Planet]
类的引用,如下所示。
[ValidateSet([Planet],ErrorMessage="Value '{0}' is invalid. Try one of: {1}")]`
将 $output="The直径 of Planet {0} is {1} km" -f $_, $planets[$_]
替换为以下两行。这些允许脚本在由 Import-CSV
创建的对象数组中查找行星,而不是在您之前创建的哈希表中查找,该哈希表已从脚本中删除:
$targetplanet = $planets | Where -Property Planet -match $_
$output = "The diameter of planet {0} is {1} km" -f $targetplanet.Planet, $targetplanet.Diameter
经过这组更改后,您的最终脚本需要如下所示:
class Planet : System.Management.Automation.IValidateSetValuesGenerator {
[String[]] GetValidValues() {
$Global:planets = Import-CSV -Path planets.csv
return ($Global:planets).Planet
}
}
Function Get-PlanetDiameter {
Param(
[Parameter(Mandatory)]
[ValidateSet([Planet],ErrorMessage="Value '{0}' is invalid. Try one of: {1}")]
$Planet
)
$Planet | Foreach-Object {
$targetplanet = $planets | Where -Property Planet -match $_
$output = "The diameter of planet {0} is {1} km" -f $targetplanet.Planet, $targetplanet.Diameter
Write-Output $output
}
}
请记住,从此时起,该脚本仅适用于 PowerShell 6.1 或更高版本
现在,您如何使用这个脚本?
运行脚本
仅仅通过执行脚本并不能直接使用新版本的脚本。所有有用的代码现在都包装在一个函数中。您需要点源该文件,以允许从 PowerShell 会话中访问该函数。
PS61> . .\Get-PlanetSize.ps1
点源化后,您现在可以在 PowerShell 会话中访问新的 Get-PlanetDiameter
函数,并使用制表符完成功能。
“所有这些工作有什么好处?”,我听到你问。 “脚本似乎以同样的方式工作,但使用代码更困难!”
尝试这个:
- 打开您之前创建的
planets.csv
文件。 - 添加具有新名称和直径的新行。
- 保存 CSV 文件。
在您最初获取脚本的同一会话中,尝试使用 Get-PlanetDiameter
查找新行星的直径。有用!
以这种方式使用类给我们带来了几个好处:
- 有效值列表现在与代码本身分开,但文件中值的任何更改都会由脚本获取。
- 该文件可以由从不访问该脚本的人维护。
- 更复杂的脚本可以从电子表格、数据库、Active Directory 或 Web API 查找信息。
正如您所看到的,当使用类提供 ValidateSet 值时,可能性几乎是无限的。
包起来
在构建 Get-PlanetSize.ps1
时,我们已经涵盖了很多基础知识,所以让我们回顾一下。
在这篇文章中您了解到:
- ValidateSet 验证属性是什么以及您可能想要使用它的原因
- 如何将 ValidateSet 添加到 PowerShell 函数或脚本
- 制表符补全如何与 ValidateSet 配合使用
- 如何使用
IgnoreCase
属性来控制您的 ValidateSet 是否区分大小写 - 如何将
ErrorMessage
属性与您的 ValidateSet 和 PowerShell 6.1 结合使用 - 如何使用类通过 PowerShell 6.1 制作动态 ValidateSet
你在等什么?立即开始使用ValidateSet!
进一步阅读
- 参数属性
- 关于课程
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag