about_Functions_Advanced_Methods
简短说明
介绍指定 CmdletBinding
属性的函数如何使用可用于编译的 cmdlet 的方法和属性。
长说明
指定 CmdletBinding
属性的函数可以通过 $PSCmdlet
变量访问其他方法和属性。 这些方法包括以下方法:
- 可用于所有函数的相同输入处理方法。
- 在执行操作之前用来获取用户反馈的
ShouldProcess
和ShouldContinue
方法。 - 用于生成错误记录的
ThrowTerminatingError
方法。 - 多个
Write
方法,用于返回不同类型的输出。
PSCmdlet 类的所有方法和属性都可用于高级函数。 有关详细信息,请参阅 System.Management.Automation.PSCmdlet。
有关 CmdletBinding
属性的详细信息,请参阅 about_Functions_CmdletBindingAttribute。 有关 CmdletBindingAttribute 类,请参阅 System.Management.Automation.Cmdlet.CmdletBindingAttribute。
输入处理方法
本部分所述的方法称为输入处理方法。 对于函数,这三种方法由函数的 begin
、process
和 end
块表示。 PowerShell 7.3 添加了 clean
块进程方法。
并非必须在函数中使用其中任何一个块。 如果不使用命名块,PowerShell 会将代码置于函数的 end
块中。 但是,如果使用这些命名块中的任何一个,或定义 dynamicparam
块,则必须将所有代码放入命名块中。
以下示例显示了一个函数的轮廓,该函数包含用于一次性预处理的 begin
块、用于多记录处理的 process
块,以及用于一次性处理后处理的 end
块。
Function Test-ScriptCmdlet
{
[CmdletBinding(SupportsShouldProcess=$True)]
param ($Parameter1)
begin{}
process{}
end{}
clean{}
}
注意
这些块适用于所有函数,而不仅仅是使用 CmdletBinding
属性的函数。
begin
此块用于为函数提供可选的一次性预处理。 PowerShell 运行时会为管道中函数的每个实例使用此块中的代码一次。
process
此块用于为函数提供逐记录处理。 可以使用 process
块而无需定义其他块。
process
块执行的次数取决于你如何使用函数以及函数接收怎样的输入。
自动变量 $_
或 $PSItem
包含管道中的当前对象,以便在 process
块中使用。
$input
自动变量包含一个仅可用于函数和脚本块的枚举器。
有关详细信息,请参阅 about_Automatic_Variables。
- 在管道开头或外部调用函数将执行
process
块一次。 - 在管道中,
process
块为到达函数的每个输入对象都执行一次。 - 如果到达函数的管道输入为空,则
process
块不会执行。-
begin
end
和clean
块仍在执行。
-
重要
如果函数参数设置为接受管道输入,并且未定义 process
块,则逐记录处理将失败。 在这种情况下,无论输入如何,函数都将只执行一次。
创建接受管道输入和使用 CmdletBinding
的函数时, process
块应使用为管道输入定义的参数变量,而不是 $_
或 $PSItem
。 例如:
function Get-SumOfNumbers {
[CmdletBinding()]
param (
[Parameter(Mandatory, Position=0, ValueFromPipeline)]
[int[]]$Numbers
)
begin { $retValue = 0 }
process {
foreach ($n in $Numbers) {
$retValue += $n
}
}
end { $retValue }
}
PS> Get-SumOfNumbers 1, 2, 3, 4
10
PS> 1,2,3,4 | Get-SumOfNumbers
10
end
此块用于为函数提供可选的一次性后处理。
clean
clean
块是在 PowerShell 7.3 中添加的。
clean
块是一种方便用户清理跨 begin
、process
和 end
块的资源的方法。 它在语义上类似于 finally
块,该块涵盖脚本函数或脚本 cmdlet 的所有其他命名块。 对于以下场景,将强制执行资源清理:
- 管道执行正常完成,没有终止错误
- 管道执行因终止错误而中断
- 通过
Select-Object -First
停止管道 - 通过 Ctrl+c 或
StopProcessing()
停止管道
清理块将丢弃写入 Success 流的任何输出。
注意
添加 clean
块属于一项中断性变更。 由于 clean
是作为关键字分析的,因此它可以阻止用户直接调用名为 clean
的命令作为脚本块中的第一个语句。 然而,这不太可能是个问题。 仍可以使用调用运算符 (& clean
) 调用该命令。
确认方法
ShouldProcess
在函数执行一个将要更改系统的操作之前,可调用此方法以请求用户确认。 函数可以基于该方法返回的布尔值继续。 只能从函数的 Process{}
块内调用此方法。
CmdletBinding
属性还必须声明函数支持 ShouldProcess
(如前面的示例所示)。
有关此方法的详细信息,请参阅 System.Management.Automation.Cmdlet.ShouldProcess。
有关如何请求确认的详细信息,请参阅请求确认。
ShouldContinue
调用此方法可请求第二条确认消息。 它应在 ShouldProcess
方法返回 $true
时调用。 有关此方法的详细信息,请参阅 System.Management.Automation.Cmdlet.ShouldContinue。
错误方法
当发生错误时,函数可以调用两个不同的方法。 发生非终止错误时,函数应调用 WriteError
方法,该方法在 Write
方法部分中进行了描述。 当发生终止错误并且函数无法继续时,它应调用 ThrowTerminatingError
方法。 还可以将 Throw
语句用于终止错误,将 Write-Error cmdlet 用于非终止错误。
有关详细信息,请参阅 System.Management.Automation.Cmdlet.ThrowTerminatingError。
写入方法
函数可以调用以下方法来返回不同类型的输出。
请注意,并非所有输出都转到管道中的下一个命令。 还可以使用各种 Write
cmdlet,例如 Write-Error
。
WriteCommandDetail
有关 WriteCommandDetails
方法的信息,请参阅 System.Management.Automation.Cmdlet.WriteCommandDetail。
WriteDebug
若要提供可用于对函数进行故障排除的信息,请让函数调用 WriteDebug
方法。
WriteDebug
方法向用户显示调试消息。 有关详细信息,请参阅 System.Management.Automation.Cmdlet.WriteDebug。
WriteError
当发生非终止错误并且函数设计为继续处理记录时,函数应调用此方法。 有关详细信息,请参阅 System.Management.Automation.Cmdlet.WriteError。
注意
如果发生终止错误,函数应调用 ThrowTerminatingError 方法。
WriteObject
WriteObject
方法允许函数将对象发送到管道中的下一个命令。 在大多数情况下,WriteObject
是函数返回数据时要使用的方法。 有关详细信息,请参阅 System.Management.Automation.PSCmdlet.WriteObject。
WriteProgress
对于其操作需要很长时间才能完成的函数,此方法允许函数调用 WriteProgress
方法,以便显示进度信息。 例如,可以显示已完成的百分比。
有关详细信息,请参阅 System.Management.Automation.PSCmdlet.WriteProgress。
WriteVerbose
若要提供有关函数执行的操作的详细信息,请让函数调用 WriteVerbose
方法,以便向用户显示详细消息。 默认情况下,不显示详细消息。 有关详细信息,请参阅 System.Management.Automation.PSCmdlet.WriteVerbose。
WriteWarning
若要提供有关可能导致意外结果的情况的信息,请让函数调用 WriteWarning 方法,以便向用户显示警告消息。 默认情况下,将显示警告消息。 有关详细信息,请参阅 System.Management.Automation.PSCmdlet.WriteWarning。
注意
还可以通过配置 $WarningPreference
变量或使用 Verbose
和 Debug
命令行选项来显示警告消息。 有关 $WarningPreference
变量的详细信息,请参阅 about_Preference_Variables。
其他方法和属性
有关可通过 $PSCmdlet
变量访问的其他方法和属性的信息,请参阅 System.Management.Automation.PSCmdlet。
例如,使用 ParameterSetName 属性可以查看所使用的参数集。 通过参数集,可以创建一个函数,以便基于运行函数时指定的参数执行不同任务。