powershell高级函数支持管道输入需用begin/process/end块及[parameter(valuefrompipeline)]属性:begin初始化资源,process逐项处理$_或参数,end汇总输出;空管道时process不执行,累积变量须在begin中声明。
powershell 中编写支持管道输入的高级函数,核心在于正确使用 begin、process 和 end 块,并配合恰当的参数绑定属性。这不是可选技巧,而是处理流式数据的标准范式。
必须声明参数绑定方式
仅靠 param 声明变量不够,需用 [Parameter(ValueFromPipeline)] 显式启用管道输入支持:
- 若希望接收单个对象(如
'hello' | My-Function),参数类型设为[string]或[object]即可 - 若需同时兼容数组传参(如
My-Function 'a','b')和管道逐项处理,推荐声明为[string[]]并在process中遍历 - 避免只依赖
$_而忽略参数名——这会让函数失去明确的接口契约,也不利于帮助文档生成
按职责分离三块逻辑
begin 块做一次性准备,process 块处理每个输入项,end 块收尾汇总:
- begin:初始化集合、打开日志文件、连接数据库等。即使管道无输入也会执行一次
-
process:真正干活的地方。自动变量
$_或$PSItem指向当前管道对象;若参数已绑定,也可直接用参数名(如$InputData) -
end:关闭资源、输出汇总结果、写入最终报告。它总在所有
process执行完毕后运行一次
注意空输入与作用域边界
当管道未传入任何对象时,process 块完全不执行,但 begin 和 end 仍会运行:
- 不要在
process中初始化累积变量(如$list = @()),否则每次调用都会重置——应放在begin中 - 若函数中用了
CmdletBinding(),所有代码必须放入命名块(begin/process/end),不能有块外语句 - PowerShell 7.3+ 新增
clean块,用于异常退出时的资源清理,但目前尚未广泛替代try/catch/finally
一个可靠模板
以下结构兼顾可读性、健壮性和兼容性:
function Convert-ToUpper {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[string[]]$Text
)
begin { $output = @() }
process {
foreach ($t in $Text) {
$output += $t.ToUpper()
}
}
end { $output }
}
该函数既支持 'hi','world' | Convert-ToUpper,也支持 Convert-ToUpper 'hi','world',返回结果一致且可被后续命令继续管道处理。











