今天在powershell.com 看見了一個很有趣的問題。問題如下,有一個csv文件,大概內容是這樣的
然後請問爲什麼這個命令不工作?
import-csv name.csv | get-service
報錯:
理論上管道應該可以通過byvalue或者bypropertyname傳遞,get-service有-computername這個選項,前面導入的csv文件也有comutername這個屬性,理論上應該自動匹配纔對啊?那麼問題出在哪裏呢?
管道的基本實現方式參見 http://beanxyz.blog.51cto.com/5570417/1678609
我們可以用trace-command 命令來跟蹤具體發生了什麼
trace-command -PSHost -name ParameterBinding -Expression{ import-csv name.csv | get-service }
首先是import-csv的命令,沒問題
然後接下來管道要把他獲取的內容傳遞給 get-service
注意看我以爲會自動匹配的computername並沒有自動匹配進去,反而是name這個參數匹配進去了!儘管他第一次匹配因爲類型不同忽略了,第二次他自動進行了一個類型轉換,強行和name匹配成功
原因何在呢? 查看一下get-service的幫助文檔。小技巧:我一般是使用-showwindows 或者-online,這樣我可以新開一個窗口進行搜索,不過win10和ps5有個bug,-show的內容不完善所以我使用在線查看。
help get-service -online
搜索byvalue,我們可以看見有兩個參數接受,分別是
-InputObject<ServiceController[]>
-Name<String[]>
搜索bypropertyname, 也有兩個參數接受這個方式:
-ComputerName<String[]>
-Name<String[]>
然後再看看position的參數, 發現-Name是設定爲1的,也就是說默認情況下如果我們沒有指定參數,他會認爲自動用-name來匹配對應的字符串!
當管道嘗試匹配的時候,因爲我們沒有指定參數,他會自動用-Name參數來進行匹配,儘管他的類型對不上,他會自動把PSCustomObject轉換成字符串進行嘗試,這樣一來類型一樣了,他就自動匹配成了-Name而不是-ComputerName,因爲後者根本沒有機會來匹配。
怎麼解決呢?很簡單我們需要明確告訴他哪些參數和屬性要配對。
比如
import-csv name.csv | get-service -name * -ComputerName {$_.computername}
或者
get-service -computername ((import-csv name.csv ).computername)
這樣就行啦。
這個命令也不會工作,儘管管道前面和後面都有一樣的名字“computerName”
get-adcomputer -filter * | select @{n='computername';e={$_.name}} |invoke-command -ScriptBlock { dir }
爲什麼?因爲
Invoke-command 的computername根本就不支持管道
他的-inputobject 接受任何類型!!也就是說任何嘗試傳遞給invoke-command的管道參數都會被接管,其他的管道參數設置是毫無用處的。
怎麼解決?和上面一樣直接跑吧 別用管道了
invoke-command -ScriptBlock { dir } -computername (get-adcomputer -filter * | select -expand name)