在上次的介绍中我们主要介绍了Windows PowerShell V2 中高级函数的一些基础概念,在本次介绍中我们将要涉及的是如何使用高级函数达到类似cmdlet的使用体验(下面就以高级函数来称呼)。
首先还是让我们来看一下高级函数是如何构成的:
Function Test-AdvancedFunction 
{
[CmdletBinding(SupportsShouldProcess=<Boolean>,
ConfirmImpact=<String>,
DefaultParameterSetName=<String>)]
Param ($Parameter1)
Begin{}
Process{}
End{}
}

大家一定注意到了最开始的CmdletBinding,接下来让我们来详细看下这个属性及它自身的一些成员属性(相关的帮助信息可以通过“help about_Functions_CmdletBindingAttribute”来查看)。
  • SupportsShouldProcess
    可选参数值为$True, $False。当设置为$True时,高级函数将支持通用参数-whatif以及-confirm。
  • ConfirmImpact
    可选参数值为High, Low, Medium, None。关于这个参数我们会在稍后通过代码实例说明。
  • DefaultParameterSetName
    代表默认的参数集名称。参数集就是我们在使用帮助命令时看到的语法内容,这部分内容将放在下次的介绍中进行说明。
为了与DynamicParam所定义的参数区别开来,我们姑且称有Param定义的参数为静态参数。接下来让我们来看下如何定义静态的参数。静态参数的定义本身并不复杂,复杂的地方在于如何选择参数的属性来达到自己想要的效果。下面给出相关参数属性的列表:
属性名
可选参数值
属性说明
Mandatory
$True, $False
指定参数是否是必要参数,强制用户输入
Position
整数
指定参数位置,如果用户没有指定具体参数名称,那么PowerShell将根据该值按序填充相应的参数
ParameterSetName
字符串
指定该参数属于哪个特定的参数集
ValueFromPipeline
$True, $False
是否接受来自管道中的值
ValueFromPipelineByPropertyName
$True, $False
是否接受来自管道中指定参数名的值
ValueFromRemainingArguments
$True, $False
是否接受来自管道中的剩余参数
HelpMessage
字符串
描述参数作用的帮助信息
Alias
字符串
指定参数的另一个名称
下面的参数是用来对用户输入的参数进行验证
AllowNull
允许对象为空
AllowEmptyString
允许字符串为空
AllowEmptyCollection
允许集合为空
ValidateCount
整数
检验可以接受的参数个数
ValidateLength
整数
检验参数的长度
ValidatePattern
正则表达式
使用正则表达式来检验参数
ValidateRange
整数范围
检验参数值是否在指定范围内
ValidateScript
表达式
使用代码来检验参数值
ValidateSet
集合
检验参数值是否在指定的属性集合中
ValidateNotNull
检验参数是否为非空对象
ValidateNotNullOrEmpty
检验参数是否为非空字符串
这里虽然给出了完整的可用参数属性列表,但并不是说我们每设置一个参数都要指定这么多属性,我们可以按需使用相应的属性。如果各位要查看如何使用具体每一个属性,可以参考这里
接下来我将给出一段模拟计算器的示例代码,我们结合代码来看如何结合参数属性定义静态参数。
Function Test-Calc
{
[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact="none")]
Param
(
[ValidateRange(1,100)]
[parameter(Mandatory=$true,
Position=0,
HelpMessage=
"请输入数字1")]
[int]$Number1,
[parameter(Mandatory=$true,
Position=1,
HelpMessage=
"操作符")]
[ValidateSet(
"+",
"-",
"*",
"/",
"Max",
"Min")]
[string]$Operator,
[ValidateRange(1,100)]
[parameter(Mandatory=$true,
Position=2,
HelpMessage=
"请输入数字2")]
[int]$Number2
)
process
{
switch ($Operator)
{
"+" {$result = $Number1 + $Number2}
"-" {$result = $Number1 - $Number2}
"*" {$result = $Number1 * $Number2}
"/" {$result = $Number1 / $Number2}
"Min" {$result = [Math]::Min($Number1,$Number2)}
"Max" {$result = [Math]::Max($Number1,$Number2)}
}
}
end
{
Write-Host
"Result : $Number1 $Operator $Number2 = $result"
}
}

首先Param后面使用的是小括号(),而不是花括号{},这点大家需要注意。其次我们有可能需要定义很多个参数,同时也会指定很多参数的属性,此时在注意合理换行的同时,也要注意括号匹配的问题。我们来看下这两个参数的定义:
[ValidateRange(1,100)]
[parameter(Mandatory=$true,
Position=0,
HelpMessage="请输入数字1")]
[int]$Number1,
[parameter(Mandatory=$true,
Position=1,
HelpMessage="操作符")]
[ValidateSet("+","-","*","/","Max","Min")]
[string]$Operator,
在最开始,我们对使用了用户参数进行验证的ValidateRange,它可以独立成行,并且使用中括号[]来定义。接着我们看到了Parameter,所有的参数属性都必须包含在Parameter后的()中,之间使用,分隔。最后我们定义参数的具体类型,同时我们需要注意不同参数之间也是用,进行分隔的,因此这里的,和不同括号可能非常让人头晕眼花,在定义的时候经常出错,所以大家定义的时候还需仔细。当然参数属性的部分,也可以写成这样:
[ValidateRange(1,100)]
[parameter(Mandatory=$true,Position=0,HelpMessage="请输入数字1")]
[int]$Number1,
[parameter(Mandatory=$true,Position=1,HelpMessage="操作符")]
[ValidateSet("+","-","*","/","Max","Min")]
[string]$Operator,
这样做的缺点也很明显,如果使用的参数属性较多或者参数属性值过长,会造成一行代码过长。因此这两种方法,大家可以视具体情况综合使用。