about_Pipelines
Krótki opis
Łączenie poleceń w potokach w programie PowerShell
Długi opis
Potok to seria poleceń połączonych przez operatory potoku (|
) (ASCII 124). Każdy operator potoku wysyła wyniki poprzedniego polecenia do następnego polecenia.
Dane wyjściowe pierwszego polecenia można wysłać do przetwarzania jako dane wejściowe do drugiego polecenia. I te dane wyjściowe mogą być wysyłane do jeszcze innego polecenia. Wynikiem jest złożony łańcuch poleceń lub potok składający się z serii prostych poleceń.
Na przykład:
Command-1 | Command-2 | Command-3
W tym przykładzie obiekty emitujące Command-1
są wysyłane do Command-2
obiektu .
Command-2
przetwarza obiekty i wysyła je do Command-3
programu . Command-3
przetwarza obiekty i wysyła je w dół potoku. Ponieważ w potoku nie ma więcej poleceń, wyniki są wyświetlane w konsoli programu .
W potoku polecenia są przetwarzane w kolejności od lewej do prawej. Przetwarzanie jest obsługiwane jako pojedyncza operacja, a dane wyjściowe są wyświetlane podczas jego generowania.
Oto prosty przykład. Następujące polecenie pobiera proces Notatnika, a następnie zatrzymuje go.
Na przykład:
Get-Process notepad | Stop-Process
Pierwsze polecenie używa Get-Process
polecenia cmdlet do pobrania obiektu reprezentującego proces Notatnika. Używa operatora potoku (|
) do wysyłania obiektu procesu do Stop-Process
polecenia cmdlet, co zatrzymuje proces Notatnika. Zwróć uwagę, że Stop-Process
polecenie nie ma parametru Name lub ID w celu określenia procesu, ponieważ określony proces jest przesyłany za pośrednictwem potoku.
Ten przykład potoku pobiera pliki tekstowe w bieżącym katalogu, wybiera tylko pliki, które mają więcej niż 10 000 bajtów długości, sortuje je według długości i wyświetla nazwę i długość każdego pliku w tabeli.
Get-ChildItem -Path *.txt |
Where-Object {$_.length -gt 10000} |
Sort-Object -Property length |
Format-Table -Property name, length
Ten potok składa się z czterech poleceń w określonej kolejności. Poniższa ilustracja przedstawia dane wyjściowe z każdego polecenia, które jest przekazywane do następnego polecenia w potoku.
Get-ChildItem -Path *.txt
| (FileInfo objects for *.txt)
V
Where-Object {$_.length -gt 10000}
| (FileInfo objects for *.txt)
| ( Length > 10000 )
V
Sort-Object -Property Length
| (FileInfo objects for *.txt)
| ( Length > 10000 )
| ( Sorted by length )
V
Format-Table -Property name, length
| (FileInfo objects for *.txt)
| ( Length > 10000 )
| ( Sorted by length )
| ( Formatted in a table )
V
Name Length
---- ------
tmp1.txt 82920
tmp2.txt 114000
tmp3.txt 114000
Korzystanie z potoków
Większość poleceń cmdlet programu PowerShell jest przeznaczona do obsługi potoków. W większości przypadków można przekazać wyniki polecenia cmdlet Get do innego polecenia cmdlet tego samego rzędu.
Możesz na przykład przekazać dane wyjściowe Get-Service
polecenia cmdlet do Start-Service
poleceń cmdlet lub Stop-Service
.
Ten przykładowy potok uruchamia usługę WMI na komputerze:
Get-Service wmi | Start-Service
Na potrzeby innego przykładu możesz przekazać dane wyjściowe Get-Item
lub Get-ChildItem
w obrębie dostawcy rejestru programu PowerShell do New-ItemProperty
polecenia cmdlet . W tym przykładzie dodano nowy wpis rejestru NoOfEmployees o wartości 8124 do klucza rejestru MyCompany.
Get-Item -Path HKLM:\Software\MyCompany |
New-ItemProperty -Name NoOfEmployees -Value 8124
Wiele poleceń cmdlet narzędzia, takich jak Get-Member
, Where-Object
, Sort-Object
, Group-Object
i Measure-Object
, jest używanych prawie wyłącznie w potokach. Do tych poleceń cmdlet można przekazać dowolny typ obiektu. W tym przykładzie pokazano, jak sortować wszystkie procesy na komputerze według liczby otwartych dojść w każdym procesie.
Get-Process | Sort-Object -Property handles
Obiekty można przesyłać potokami do poleceń cmdlet formatowania, eksportowania i danych wyjściowych, takich jak Format-List
, , Format-Table
Export-Clixml
, Export-CSV
, i Out-File
.
W tym przykładzie Format-List
pokazano, jak za pomocą polecenia cmdlet wyświetlić listę właściwości obiektu procesu.
Get-Process winlogon | Format-List -Property *
Możesz również przekazać dane wyjściowe poleceń natywnych do poleceń cmdlet programu PowerShell. Na przykład:
PS> ipconfig.exe | Select-String -Pattern 'IPv4'
IPv4 Address. . . . . . . . . . . : 172.24.80.1
IPv4 Address. . . . . . . . . . . : 192.168.1.45
IPv4 Address. . . . . . . . . . . : 100.64.108.37
Ważne
Strumienie powodzenia i błędu są podobne do strumieni stdin i stderr innych powłok. Jednak stdin nie jest połączony z potokiem programu PowerShell dla danych wejściowych. Aby uzyskać więcej informacji, zobacz about_Redirection.
Z odrobiną praktyki przekonasz się, że łączenie prostych poleceń w potoki pozwala zaoszczędzić czas i wpisywanie i zwiększa wydajność wykonywania skryptów.
Jak działają potoki
W tej sekcji wyjaśniono, jak obiekty wejściowe są powiązane z parametrami polecenia cmdlet i przetwarzane podczas wykonywania potoku.
Akceptuje dane wejściowe potoku
Aby obsługiwać potokowanie, odbierające polecenie cmdlet musi mieć parametr, który akceptuje dane wejściowe potoku. Get-Help
Użyj polecenia z opcjami Pełna lub Parametr, aby określić, które parametry polecenia cmdlet akceptują dane wejściowe potoku.
Aby na przykład określić, które parametry Start-Service
polecenia cmdlet akceptują dane wejściowe potoku, wpisz:
Get-Help Start-Service -Full
lub
Get-Help Start-Service -Parameter *
Pomoc dla Start-Service
polecenia cmdlet pokazuje, że tylko parametry InputObject i Name akceptują dane wejściowe potoku.
-InputObject <ServiceController[]>
Specifies ServiceController objects representing the services to be started.
Enter a variable that contains the objects, or type a command or expression
that gets the objects.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByValue)
Accept wildcard characters? false
-Name <String[]>
Specifies the service names for the service to be started.
The parameter name is optional. You can use Name or its alias, ServiceName,
or you can omit the parameter name.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? false
Podczas wysyłania obiektów za pośrednictwem potoku do Start-Service
programu Program PowerShell próbuje skojarzyć obiekty z parametrami InputObject i Name .
Metody akceptowania danych wejściowych potoku
Parametry poleceń cmdlet mogą akceptować dane wejściowe potoku na jeden z dwóch różnych sposobów:
ByValue: parametr akceptuje wartości zgodne z oczekiwanym typem platformy .NET lub, które można przekonwertować na ten typ.
Na przykład parametr Name akceptowania danych wejściowych potoku
Start-Service
według wartości. Może on akceptować obiekty ciągów lub obiekty, które można przekonwertować na ciągi.ByPropertyName: Parametr akceptuje dane wejściowe tylko wtedy, gdy obiekt wejściowy ma właściwość o tej samej nazwie co parametr.
Na przykład parametr
Start-Service
Name obiektu może akceptować obiekty, które mają właściwość Name . Aby wyświetlić listę właściwości obiektu, należy przekazać go doGet-Member
elementu .
Niektóre parametry mogą akceptować obiekty według zarówno wartości, jak i nazwy właściwości, co ułatwia wprowadzanie danych wejściowych z potoku.
Powiązanie parametrów
Podczas potokowania obiektów z jednego polecenia do innego polecenia program PowerShell próbuje skojarzyć potokowe obiekty z parametrem odbierającego polecenia cmdlet.
Składnik powiązania parametrów programu PowerShell kojarzy obiekty wejściowe z parametrami polecenia cmdlet zgodnie z następującymi kryteriami:
- Parametr musi akceptować dane wejściowe z potoku.
- Parametr musi zaakceptować typ wysyłanego obiektu lub typ, który można przekonwertować na oczekiwany typ.
- Parametr nie został użyty w poleceniu .
Na przykład Start-Service
polecenie cmdlet ma wiele parametrów, ale tylko dwa z nich, Name i InputObject akceptują dane wejściowe potoku. Parametr Name przyjmuje ciągi, a parametr InputObject przyjmuje obiekty usługi. W związku z tym można potokować ciągi, obiekty usługi i obiekty z właściwościami, które można przekonwertować na ciąg lub obiekty usługi.
Program PowerShell zarządza powiązaniem parametrów tak wydajnie, jak to możliwe. Nie można sugerować ani wymuszać powiązania programu PowerShell z określonym parametrem. Polecenie kończy się niepowodzeniem, jeśli program PowerShell nie może powiązać potokowych obiektów.
Aby uzyskać więcej informacji na temat rozwiązywania problemów z błędami powiązań, zobacz Badanie błędów potoku w dalszej części tego artykułu.
Przetwarzanie jednorazowe
Potokowanie obiektów do polecenia jest podobne do użycia parametru polecenia w celu przesłania obiektów. Przyjrzyjmy się przykładowi potoku. W tym przykładzie używamy potoku do wyświetlania tabeli obiektów usługi.
Get-Service | Format-Table -Property Name, DependentServices
Funkcjonalnie jest to podobne do użycia parametru InputObject obiektu Format-Table
w celu przesłania kolekcji obiektów.
Na przykład możemy zapisać kolekcję usług w zmiennej przekazanej przy użyciu parametru InputObject .
$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices
Można też osadzić polecenie w parametrze InputObject .
Format-Table -InputObject (Get-Service) -Property Name, DependentServices
Istnieje jednak ważna różnica. Podczas potoku wielu obiektów do polecenia program PowerShell wysyła obiekty do polecenia pojedynczo. Gdy używasz parametru polecenia, obiekty są wysyłane jako pojedynczy obiekt tablicy. Ta niewielka różnica ma znaczące konsekwencje.
Podczas wykonywania potoku program PowerShell automatycznie wylicza dowolny typ implementujący IEnumerable
interfejs lub jego ogólny odpowiednik. Wyliczone elementy są wysyłane za pośrednictwem potoku pojedynczo. Program PowerShell wylicza również typy System.Data.DataTable za pomocą Rows
właściwości .
Istnieje kilka wyjątków od automatycznego wyliczania.
- Należy wywołać metodę
GetEnumerator()
tabel skrótów, typów implementującychIDictionary
interfejs lub jego odpowiednik ogólny oraz typy System.Xml.XmlNode . - Klasa System.String implementuje
IEnumerable
element , jednak program PowerShell nie wylicza obiektów ciągów.
W poniższych przykładach tablica i tabela skrótów są przesyłane potokiem do Measure-Object
polecenia cmdlet w celu zliczenia liczby obiektów odebranych z potoku. Tablica ma wiele elementów członkowskich, a tabela skrótów ma wiele par klucz-wartość. Tylko tablica jest wyliczana pojedynczo.
@(1,2,3) | Measure-Object
Count : 3
Average :
Sum :
Maximum :
Minimum :
Property :
@{"One"=1;"Two"=2} | Measure-Object
Count : 1
Average :
Sum :
Maximum :
Minimum :
Property :
Podobnie, jeśli potokujesz wiele obiektów procesów z Get-Process
polecenia cmdlet do Get-Member
polecenia cmdlet, program PowerShell wysyła każdy obiekt procesu, jeden naraz, do Get-Member
. Get-Member
wyświetla klasę .NET (typ) obiektów procesu oraz ich właściwości i metody.
Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize
...
Uwaga
Get-Member
eliminuje duplikaty, więc jeśli obiekty są tego samego typu, wyświetla tylko jeden typ obiektu.
Jeśli jednak używasz parametru InputObject klasy Get-Member
, Get-Member
otrzyma tablicę obiektów System.Diagnostics.Process jako pojedynczą jednostkę. Wyświetla właściwości tablicy obiektów. (Zanotuj symbol tablicy ([]
) po nazwie typu System.Object .
Na przykład:
Get-Member -InputObject (Get-Process)
TypeName: System.Object[]
Name MemberType Definition
---- ---------- ----------
Count AliasProperty Count = Length
Address Method System.Object& Address(Int32 )
Clone Method System.Object Clone()
...
Ten wynik może nie być zamierzony. Ale po jego zrozumieniu możesz go użyć. Na przykład wszystkie obiekty tablicy mają właściwość Count . Można jej użyć do zliczenia liczby procesów uruchomionych na komputerze.
Na przykład:
(Get-Process).count
Należy pamiętać, że obiekty wysyłane w potoku są dostarczane pojedynczo.
Używanie poleceń natywnych w potoku
Program PowerShell umożliwia dołączanie natywnych poleceń zewnętrznych do potoku. Należy jednak pamiętać, że potok programu PowerShell jest zorientowany obiektowo i nie obsługuje nieprzetworzonych danych bajtowych.
Potokowanie lub przekierowywanie danych wyjściowych z programu natywnego, który generuje nieprzetworzone dane bajtowe konwertuje dane wyjściowe na ciągi platformy .NET. Ta konwersja może spowodować uszkodzenie nieprzetworzonych danych wyjściowych.
Aby obejść ten problem, wywołaj polecenia natywne przy użyciu poleceń i użyj cmd.exe /c
|
operatorów i >
dostarczonych przez powłokę natywną.
Badanie błędów potoku
Jeśli program PowerShell nie może skojarzyć obiektów potokowych z parametrem odbierającego polecenia cmdlet, polecenie kończy się niepowodzeniem.
W poniższym przykładzie próbujemy przenieść wpis rejestru z jednego klucza rejestru do innego. Polecenie Get-Item
cmdlet pobiera ścieżkę docelową, która jest następnie potokowana do Move-ItemProperty
polecenia cmdlet. Polecenie Move-ItemProperty
określa bieżącą ścieżkę i nazwę wpisu rejestru do przeniesienia.
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
Polecenie kończy się niepowodzeniem, a program PowerShell wyświetla następujący komunikat o błędzie:
Move-ItemProperty : The input object can't be bound to any parameters for
the command either because the command doesn't take pipeline input or the
input and its properties do not match any of the parameters that take
pipeline input.
At line:1 char:23
+ $a | Move-ItemProperty <<<< -Path HKLM:\Software\MyCompany\design -Name p
Aby zbadać, użyj Trace-Command
polecenia cmdlet , aby śledzić składnik powiązania parametrów programu PowerShell. Poniższy przykład śledzi powiązanie parametru podczas wykonywania potoku. Parametr PSHost wyświetla wyniki śledzenia w konsoli, a parametr FilePath wysyła wyniki śledzenia do pliku w celu późniejszego debug.txt
odwołania.
Trace-Command -Name ParameterBinding -PSHost -FilePath debug.txt -Expression {
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
}
Wyniki śledzenia są długie, ale pokazują wartości powiązane z Get-Item
poleceniem cmdlet, a następnie nazwane wartości powiązane z Move-ItemProperty
poleceniem cmdlet.
...
BIND NAMED cmd line args [`Move-ItemProperty`]
BIND arg [HKLM:\Software\MyCompany\design] to parameter [Path]
...
BIND arg [product] to parameter [Name]
...
BIND POSITIONAL cmd line args [`Move-ItemProperty`]
...
Na koniec pokazuje, że próba powiązania ścieżki z parametrem Move-ItemProperty
Destination zakończyła się niepowodzeniem.
...
BIND PIPELINE object to parameters: [`Move-ItemProperty`]
PIPELINE object TYPE = [Microsoft.Win32.RegistryKey]
RESTORING pipeline parameter's original values
Parameter [Destination] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
...
Get-Help
Użyj polecenia cmdlet, aby wyświetlić atrybuty parametru Destination.
Get-Help Move-ItemProperty -Parameter Destination
-Destination <String>
Specifies the path to the destination location.
Required? true
Position? 1
Default value None
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
Wyniki pokazują, że miejsce docelowe przyjmuje dane wejściowe potoku tylko "według nazwy właściwości". W związku z tym obiekt potokowy musi mieć właściwość o nazwie Destination.
Użyj Get-Member
polecenia , aby wyświetlić właściwości obiektu pochodzącego z Get-Item
obiektu .
Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member
Dane wyjściowe pokazują, że element jest obiektem Microsoft.Win32.RegistryKey , który nie ma właściwości Destination . Wyjaśnia to, dlaczego polecenie nie powiodło się.
Parametr Path akceptuje dane wejściowe potoku według nazwy lub wartości.
Get-Help Move-ItemProperty -Parameter Path
-Path <String[]>
Specifies the path to the current location of the property. Wildcard
characters are permitted.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? true
Aby naprawić polecenie, musimy określić miejsce docelowe w poleceniu Move-ItemProperty
cmdlet i użyć Get-Item
polecenia , aby uzyskać ścieżkę elementu, który chcemy przenieść.
Na przykład:
Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product
Kontynuacja linii wewnętrznej
Jak już wspomniano, potok jest serią poleceń połączonych przez operatory potoku (|
), zwykle napisanych w jednym wierszu. Jednak w celu zapewnienia czytelności program PowerShell umożliwia podzielenie potoku między wiele wierszy. Gdy operator potoku jest ostatnim tokenem w wierszu, analizator programu PowerShell łączy następny wiersz z bieżącym poleceniem, aby kontynuować konstruowanie potoku.
Na przykład następujący potok jednowierszowy:
Command-1 | Command-2 | Command-3
można napisać jako:
Command-1 |
Command-2 |
Command-3
Spacje wiodące w kolejnych wierszach nie są istotne. Wcięcie zwiększa czytelność.