PowerShell管道如何工作 – 第1部分?


PowerShell透過管道結構變得更容易。使用管道結構,我們可以將左側命令輸出或字串的輸入傳遞到命令右側作為輸入。例如,

Get-Service | Out-File c:\services.txt

在上面的示例中,我們將**Get-Service**的輸出作為物件傳遞給**Out-File**命令,它是管道的右側,作為輸入。在詳細瞭解管道如何工作之前,我們需要了解我們編寫的每個命令都會產生輸出,並且該輸出已由PowerShell使用管道進行格式化。

例如,**Get-Process**命令,如果我們不格式化此命令,則實際的預設命令為:

Get-Process | Out-Default | Out-Host

**Out-Default**和**Out-Host**是不可見的,但實際上在後臺執行。**Out-Default**設定預設格式,而**Out-Host**命令將輸出列印到控制檯。

在管道結構中,命令的右側從輸出的左側獲取輸入。因此,我們需要了解,我們究竟可以將什麼傳遞給管道,我們不能傳遞隨機的東西,例如程序的名稱或PID作為管道,如下所示。

"PowerShell" | Get-Process


"1002" | Get-Process

上面的命令將生成錯誤,指出上面的命令不將提供的輸入作為管道輸入。

Get-Process: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input
and its properties do not match any of the parameters that take pipeline input.

而對於Get-Service,我們可以傳遞名稱。

PS C:\> "Winrm","Spooler" | Get-Service

Status    Name     DisplayName
------    ----     -----------
Running   Winrm    Windows Remote Management (WS-Managem…
Running   Spooler  Print Spooler

以下是解釋。要檢查我們究竟可以將什麼作為輸入傳遞到命令的右側,我們需要使用**Get-Command**以及屬性名稱ParameterSet。您還可以使用**Get-Help**命令。

(Get-Command Get-Service).ParameterSets.Parameters

執行上述命令後,請注意這兩個屬性**ValueFromPipeLine**和**ValueFromPipelineByPropertyName**,並檢查**True**值。讓我們過濾掉這些屬性。

在本文中,我們介紹了**ValueFromPipleLine**屬性。**valueFromPipelineByPropertyName**引數將在下一篇文章(第2部分)中介紹。

(Get-Command Get-Service).ParameterSets.parameters | where{$_.ValueFromPipeline -eq 'True'} | Select Name,ParameterType

輸出

Name ParameterType
---- -------------
Name System.String[]
InputObject System.ServiceProcess.ServiceController[]

從上面的輸出中,我們可以將**Name**作為輸入物件,其型別為**String[]**。這意味著我們可以傳遞多個服務名稱,這與前面示例中討論的相同。

PS C:\> "Winrm","Spooler" | Get-Service

Status Name DisplayName
------ ---- -----------
Running Winrm Windows Remote Management (WS-Managem…
Running Spooler Print Spooler

第二個是InputObject,其型別為ServiceController[]。當您使用命令的Get-Member時,您可以在第一行看到此型別,並且將獲得TypeName。

PS C:\> Get-Service | Get-Member
TypeName: System.Service.ServiceController

讓我們以Stop-Service命令為例,以便更好地理解它,

(Get-Command Stop-Service).ParameterSets.parameters | where{$_.ValueFromPipeline -eq 'True'} | Select Name,ParameterType
Name ParameterType
---- -------------
InputObject System.Diagnostics.Process[]

因此,**Stop-Process**命令僅接受Process陣列作為輸入,並且如果您檢查**Get-Process**,其成員型別也是**System.Diagnostics.process**。這意味著我們可以使用管道將整個Get-Process作為輸入傳遞給**Stop-Process**。

PS C:\> Get-Process | gm

TypeName: System.Diagnostics.Process

Get-Process | Stop-Process

這意味著如果我們傳遞程序的名稱或程序ID,則它不應該工作。

PS C:\> "2916" | Stop-Process
InvalidArgument: (2916:String) [Stop-Process], ParameterBindingException

PS C:\> "Notepad" | Stop-Process
InvalidArgument: (Notepad:String) [Stop-Process], ParameterBindingException

在上面的示例中,傳遞程序ID或程序名稱不起作用,因為管道不接受該輸入。

更新於: 2020年10月16日

135 次檢視

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.