首页/系统/Windows 运维速查/管道传递对象(不是文本)
PowerShell 基础66 条

管道传递对象(不是文本)

PowerShell 管道的核心模型:上游命令输出 .NET 对象,下游直接按属性过滤与取值,这是与 CMD/Bash 文本管道的主要区别。

Windows 运维速查系统更新于 2026-10-13

管道传的是对象

PowerShell 的管道与 CMD、Bash 有本质区别:上游命令把 .NET 对象逐个写进管道,下游命令直接读对象的属性与方法,而不是按行解析文本。所以 Get-Process | Where-Object CPU -gt 100 是在比较数值属性,不需要切列,也不受列宽或空格数量影响。只有当对象流到达管道最末端准备显示时,格式化系统才把它渲染成表格。理解了这一层,就能解释为什么管道里能排序、能求和,也能解释为什么 Format-* 一旦出现就不该再往后接计算。

基本信息

适用平台Windows PowerShell 5.1 与 PowerShell 7 及以上,模型一致
核心模型管道中流动的是对象,属性与方法随对象一起传递
常见环节产生对象、过滤、投影、排序聚合、输出格式化
探路手段用 Get-Member 查看当前管道中对象的类型与可用成员
运算符比较用 -eq、-gt、-like、-match 等,与 CMD 的 == 写法无关

典型使用场景

  • 资源排查:按 CPU、内存等属性排序取前几名,不必再看固定宽度的表格
  • 批量清洗:先用 Where-Object 筛出目标对象,再交给 ForEach-Object 统一处理
  • 生成报表:管道末端接 Export-Csv 或 ConvertTo-Json,直接落成结构化文件
  • 计算汇总:Measure-Object 在管道里求和、求平均、计数
  • 结果复用:把管道结果存入变量,后续按属性反复取用而不必重跑命令
  • 编写可组合函数:函数声明接受管道输入后,就能与内置 cmdlet 混搭

管道各环节职责

环节类型职责代表命令
产生对象从系统或文件读入原始数据Get-Process、Get-ChildItem、Import-Csv
过滤筛选按条件保留部分对象Where-Object、Select-Object -First
投影派生取需要的列或算出新列Select-Object Name, @{n='MB';e={...}}
排序聚合重排顺序、分组、统计Sort-Object、Group-Object、Measure-Object
输出格式化渲染成表格或写入文件Format-Table、Export-Csv、Out-File

常用示例

常用示例
# 上游产生对象,下游直接按属性过滤,无需解析文本
Get-Process | Where-Object CPU -gt 100 | Select-Object Name, Id, CPU
# 按大小排序取前 5,Length 是数值属性而非字符串
Get-ChildItem $env:TEMP -File | Sort-Object Length -Descending | Select-Object -First 5 Name, Length
# 在管道里做统计
Get-ChildItem D:\Logs -File | Measure-Object Length -Sum
# 先看清对象有哪些属性,再决定取哪几列
Get-Service | Get-Member -MemberType Property
# 格式化只能放在末端,之后不要再接计算
Get-Process | Sort-Object WS -Descending | Select-Object -First 5 | Format-Table Name, WS

常见对象与关键属性

命令对象类型常用属性
Get-ProcessSystem.Diagnostics.ProcessName、Id、CPU、WorkingSet64、Path
Get-ServiceServiceControllerName、DisplayName、Status、StartType
Get-ChildItemFileInfo 与 DirectoryInfoName、Length、LastWriteTime、FullName
Get-ItemPropertyPSCustomObject(结构随来源变化)注册表值、文件属性等键值
管道是流式的:对象逐个流过各环节,不会等上游全部产完再交给下游。所以 Select-Object -First 会提前截断上游,日志里出现「管道已停止」提示多与此有关。
自定义函数想参与管道,需要给参数加 ValueFromPipeline 标记并在 process 块里处理当前对象,否则函数只能一次性接收整批输入,行为与内置 cmdlet 不一致。

与 CMD 管道的区别

  • CMD 管道传的是文本行,下游只能做字符串匹配,列位置或空格一变就失效
  • PowerShell 管道传对象,下游按属性名取值,输出列增减不影响逻辑
  • CMD 的竖线后面只能接外部程序,PowerShell 里既能接内置 cmdlet 也能接外部程序
  • 外部程序进入 PowerShell 管道时仍是纯文本,需要先解析成对象才能享受属性过滤
外部程序输出进入管道时是字符串,必须先用 ConvertFrom-Csv、ConvertFrom-Json 或正则拆解成对象,才能按属性过滤;反过来把对象交给外部程序之前,通常要先转成文本形式。

易错点

  • 把管道输出当文本切分:对象的字符串表示会随显示格式变化,应直接引用 $_.属性名,切列在换语言换终端后必坏
  • 在管道中间使用 Format-Table 或 Format-List:格式化对象会破坏后续计算与导出,Format-* 必须放在最后一步
  • 忽略管道逐对象执行的语义:在管道中给外部变量赋值或累加,得到的往往是最后一个对象的结果,复杂统计应改用 foreach 语句
  • 假定 Get-* 一定返回集合:只有一个匹配项时返回单个对象,用下标取值会失败,需要时可加 @() 包裹成数组
  • 在 Where-Object 简写形式里塞表达式:简写只支持「属性 运算符 值」,算术运算与函数调用必须写成脚本块 {}

数据来源与参考

  • Microsoft Learn:about_Pipelines
  • Microsoft Learn:about_Objects

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌