Informacje o potokach
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 drugiego polecenia. Te dane wyjściowe mogą być wysyłane do kolejnego 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 elementu Command-2
.
Command-2
przetwarza obiekty i wysyła je do programu Command-3
. 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, które zatrzymuje proces Notatnika. Zwróć uwagę, że Stop-Process
polecenie nie ma parametru Name lub ID do 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, ponieważ jest ono 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 nounu.
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
W innym przykładzie można przekazać dane wyjściowe Get-Item
polecenia lub Get-ChildItem
w ramach dostawcy rejestru programu PowerShell do New-ItemProperty
polecenia cmdlet. W tym przykładzie dodano nowy wpis rejestru NoOfEmployees z 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 niemal wyłącznie w potokach. Do tych poleceń cmdlet można przekazać potoki dowolnego typu 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 *
Dzięki odrobinie praktyki przekonasz się, że łączenie prostych poleceń w potoki pozwala zaoszczędzić czas i wpisywanie tekstu oraz zwiększa wydajność 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 parametru akceptuje dane wejściowe potoku
Start-Service
według wartości. Może on akceptować obiekty lub obiekty ciągów, 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 potokiem 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ć obiekty potokowe 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 akceptować 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 zasugerować ani wymusić 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 w Format-Table
celu przesłania kolekcji obiektów.
Na przykład możemy zapisać kolekcję usług w zmiennej przekazywanej 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. W przypadku użycia 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, który implementuje IEnumerable
interfejs i wysyła elementy członkowskie za pośrednictwem potoku pojedynczo. Wyjątek to [hashtable]
, który wymaga wywołania GetEnumerator()
metody .
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 w przypadku potoku wielu obiektów procesu z Get-Process
polecenia cmdlet do Get-Member
polecenia cmdlet program PowerShell wysyła każdy obiekt procesu po jednym naraz do polecenia 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 tablicowe mają właściwość Count . Umożliwia to zliczenie liczby procesów uruchomionych na komputerze.
Na przykład
(Get-Process).count
Należy pamiętać, że obiekty wysyłane w dół potoku są dostarczane pojedynczo.
Badanie błędów potoku
Gdy 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 parametrów 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 Get-Item
z 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 pokazano, że próba powiązania ścieżki z parametrem Move-ItemProperty
Destination nie powiodła się.
...
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
...
Użyj polecenia cmdlet, Get-Help
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(Miejsce docelowe).
Użyj polecenia Get-Member
, 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 rozwiązać ten problem, musimy określić miejsce docelowe w Move-ItemProperty
poleceniu cmdlet i użyć polecenia Get-Item
, 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 wiersza wewnętrznego
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 na wiele wierszy.
Gdy operator potoku jest ostatnim tokenem w wierszu, analizator programu PowerShell łączy następny wiersz z bieżącym poleceniem w celu kontynuowania budowy 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ą znaczące. Wcięcie zwiększa czytelność.