Trace-Commnd 跟踪管道参数传递

本文探讨了PowerShell中管道匹配的问题,特别是当CSV文件的数据通过管道传递给Get-Service命令时出现的错误。文章解释了为何计算机名称未能正确匹配,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在powershell.com 看见了一个很有趣的问题。问题如下,有一个csv文件,大概内容是这样的

wKioL1bov12Cq2-NAAAJxMn4ZLE508.png


然后请问为什么这个命令不工作?


1
import-csv  name.csv |  get-service

报错:

wKioL1bov2HwbrdZAABRYtMWCx8609.png


理论上管道应该可以通过byvalue或者bypropertyname传递,get-service有-computername这个选项,前面导入的csv文件也有comutername这个属性,理论上应该自动匹配才对啊?那么问题出在哪里呢?

管道的基本实现方式参见 http://beanxyz.blog.51cto.com/5570417/1678609



我们可以用trace-command 命令来跟踪具体发生了什么

1
2
3
trace-command  -PSHost -name ParameterBinding -Expression{
import-csv  name.csv |  get-service
}

首先是import-csv的命令,没问题

wKiom1bowFCB3uaOAABnVGaWRSM955.png

然后接下来管道要把他获取的内容传递给 get-service


注意看我以为会自动匹配的computername并没有自动匹配进去,反而是name这个参数匹配进去了!尽管他第一次匹配因为类型不同忽略了,第二次他自动进行了一个类型转换,强行和name匹配成功

wKiom1bo0huQADg0AAGFJlLHdwk665.png


原因何在呢? 查看一下get-service的帮助文档。小技巧:我一般是使用-showwindows 或者-online,这样我可以新开一个窗口进行搜索,不过win10和ps5有个bug,-show的内容不完善所以我使用在线查看。

1
help  get-service  -online


搜索byvalue,我们可以看见有两个参数接受,分别是

-InputObject<ServiceController[]>

-Name<String[]>


搜索bypropertyname, 也有两个参数接受这个方式:

-ComputerName<String[]>

-Name<String[]>


然后再看看position的参数, 发现-Name是设定为1的,也就是说默认情况下如果我们没有指定参数,他会认为自动用-name来匹配对应的字符串!


wKiom1bo0qbxFvbHAABcEQEMmxA214.png


当管道尝试匹配的时候,因为我们没有指定参数,他会自动用-Name参数来进行匹配,尽管他的类型对不上,他会自动把PSCustomObject转换成字符串进行尝试,这样一来类型一样了,他就自动匹配成了-Name而不是-ComputerName,因为后者根本没有机会来匹配。

wKioL1bowrzSsGkbAAAnQXvGXhs280.png


怎么解决呢?很简单我们需要明确告诉他哪些参数和属性要配对。

比如

1
import-csv  name.csv |  get-service  -name * -ComputerName { $_ .computername}


或者

1
get-service  -computername (( import-csv  name.csv ).computername)

这样就行啦。


还有一个类似的例子 (http://powershell.com/cs/blogs/donjones/archive/2011/12/10/troubleshooting-pipeline-parameter-binding-by-peeking-inside.aspx)


这个命令也不会工作,尽管管道前面和后面都有一样的名字“computerName”

1
get-adcomputer  - filter  * | select @{n= 'computername' ;e={ $_ .name}}  |invoke -command -ScriptBlock { dir }


为什么?因为

  1. Invoke-command 的computername根本就不支持管道

  2. 他的-inputobject 接受任何类型!!也就是说任何尝试传递给invoke-command的管道参数都会被接管,其他的管道参数设置是毫无用处的。


wKioL1bo2ZeQRS9UAADzoUyIqBw239.png

    wKioL1bo2g6hN0zqAABVv-HXO9U776.png

怎么解决?和上面一样直接跑吧 别用管道了

1
invoke-command  -ScriptBlock { dir } -computername ( get-adcomputer  - filter  * | select -expand name)









本文转自 beanxyz 51CTO博客,原文链接:http://blog.51cto.com/beanxyz/1751700,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值