about_Pipelines
Korte beschrijving
Opdrachten combineren in pijplijnen in PowerShell
Lange beschrijving
Een pijplijn is een reeks opdrachten die zijn verbonden door pijplijnoperators (|
) (ASCII 124). Elke pijplijnoperator verzendt de resultaten van de voorgaande opdracht naar de volgende opdracht.
De uitvoer van de eerste opdracht kan worden verzonden voor verwerking als invoer voor de tweede opdracht. En die uitvoer kan worden verzonden naar nog een andere opdracht. Het resultaat is een complexe opdrachtketen of pijplijn die bestaat uit een reeks eenvoudige opdrachten.
Bijvoorbeeld:
Command-1 | Command-2 | Command-3
In dit voorbeeld worden de objecten die Command-1
worden verzonden naar Command-2
.
Command-2
verwerkt de objecten en verzendt ze naar Command-3
. Command-3
verwerkt de objecten en verzendt ze in de pijplijn. Omdat de pijplijn geen opdrachten meer bevat, worden de resultaten weergegeven in de console.
In een pijplijn worden de opdrachten van links naar rechts verwerkt. De verwerking wordt verwerkt als één bewerking en de uitvoer wordt weergegeven terwijl deze wordt gegenereerd.
Hier volgt een eenvoudig voorbeeld. Met de volgende opdracht wordt het Kladblok-proces ophaalt en vervolgens gestopt.
Bijvoorbeeld:
Get-Process notepad | Stop-Process
De eerste opdracht gebruikt de Get-Process
cmdlet om een object op te halen dat het Kladblok-proces vertegenwoordigt. Er wordt een pijplijnoperator () gebruikt|
om het procesobject naar de Stop-Process
cmdlet te verzenden, waardoor het Kladblok-proces wordt gestopt. U ziet dat de Stop-Process
opdracht geen naam - of id-parameter heeft om het proces op te geven, omdat het opgegeven proces via de pijplijn wordt verzonden.
In dit pijplijnvoorbeeld worden de tekstbestanden in de huidige map opgehaald, worden alleen de bestanden geselecteerd die meer dan 10.000 bytes lang zijn, worden ze gesorteerd op lengte en worden de naam en lengte van elk bestand in een tabel weergegeven.
Get-ChildItem -Path *.txt |
Where-Object {$_.length -gt 10000} |
Sort-Object -Property length |
Format-Table -Property name, length
Deze pijplijn bestaat uit vier opdrachten in de opgegeven volgorde. In de volgende afbeelding ziet u de uitvoer van elke opdracht wanneer deze wordt doorgegeven aan de volgende opdracht in de pijplijn.
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
Pijplijnen gebruiken
De meeste PowerShell-cmdlets zijn ontworpen ter ondersteuning van pijplijnen. In de meeste gevallen kunt u de resultaten van een get-cmdletdoorsnijden naar een andere cmdlet van hetzelfde zelfstandig naamwoord.
U kunt bijvoorbeeld de uitvoer van de Get-Service
cmdlet doorsluizen naar de Start-Service
cmdlets of Stop-Service
.
Met deze voorbeeldpijplijn wordt de WMI-service op de computer gestart:
Get-Service wmi | Start-Service
In een ander voorbeeld kunt u de uitvoer van Get-Item
of Get-ChildItem
in de PowerShell-registerprovider doorspepen naar de New-ItemProperty
cmdlet. In dit voorbeeld wordt een nieuwe registervermelding, NoOfEmployees, met de waarde 8124, toegevoegd aan de registersleutel MyCompany .
Get-Item -Path HKLM:\Software\MyCompany |
New-ItemProperty -Name NoOfEmployees -Value 8124
Veel van de cmdlets voor hulpprogramma's, zoals Get-Member
, Where-Object
, Sort-Object
, Group-Object
, en Measure-Object
worden bijna uitsluitend gebruikt in pijplijnen. U kunt elk objecttype doorsluizen naar deze cmdlets. In dit voorbeeld ziet u hoe u alle processen op de computer sorteert op het aantal geopende ingangen in elk proces.
Get-Process | Sort-Object -Property handles
U kunt objecten doorsluizen naar de cmdlets voor opmaak, export en uitvoer, zoals Format-List
, Format-Table
, Export-Clixml
, Export-CSV
en Out-File
.
In dit voorbeeld ziet u hoe u de Format-List
cmdlet gebruikt om een lijst met eigenschappen voor een procesobject weer te geven.
Get-Process winlogon | Format-List -Property *
U kunt ook de uitvoer van systeemeigen opdrachten doorsluizen naar PowerShell-cmdlets. Bijvoorbeeld:
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
Belangrijk
De stromen Success en Error zijn vergelijkbaar met de stromen stdin en stderr van andere shells. Stdin is echter niet verbonden met de PowerShell-pijplijn voor invoer. Zie about_Redirection voor meer informatie.
Met een beetje oefening zult u merken dat het combineren van eenvoudige opdrachten in pijplijnen tijd en typen bespaart en uw scripting efficiënter maakt.
Hoe pijplijnen werken
In deze sectie wordt uitgelegd hoe invoerobjecten worden gebonden aan cmdlet-parameters en worden verwerkt tijdens het uitvoeren van de pijplijn.
Accepteert pijplijninvoer
Als u pipelining wilt ondersteunen, moet de ontvangende cmdlet een parameter hebben die pijplijninvoer accepteert. Gebruik de Get-Help
opdracht met de opties Volledig of Parameter om te bepalen welke parameters van een cmdlet pijplijninvoer accepteren.
Als u bijvoorbeeld wilt bepalen welke van de parameters van de Start-Service
cmdlet pijplijninvoer accepteert, typt u:
Get-Help Start-Service -Full
of
Get-Help Start-Service -Parameter *
De Help voor de Start-Service
cmdlet laat zien dat alleen de parameters InputObject en Name pijplijninvoer accepteren.
-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
Wanneer u objecten via de pijplijn naar Start-Service
verzendt, probeert PowerShell de objecten te koppelen aan de parameters InputObject en Name .
Methoden voor het accepteren van pijplijninvoer
Cmdlets-parameters kunnen pijplijninvoer op twee verschillende manieren accepteren:
ByValue: de parameter accepteert waarden die overeenkomen met het verwachte .NET-type of die kunnen worden geconverteerd naar dat type.
De parameter Name van
Start-Service
accepteert bijvoorbeeld pijplijninvoer op waarde. Het kan tekenreeksobjecten accepteren of objecten die kunnen worden geconverteerd naar tekenreeksen.ByPropertyName: de parameter accepteert alleen invoer wanneer het invoerobject een eigenschap heeft met dezelfde naam als de parameter.
De parameter Name van
Start-Service
kan bijvoorbeeld objecten accepteren die de eigenschap Name hebben. Als u de eigenschappen van een object wilt weergeven, sluist u het door naarGet-Member
.
Sommige parameters kunnen objecten accepteren op basis van zowel de waarde als de eigenschapsnaam, waardoor het gemakkelijker is om invoer uit de pijplijn te nemen.
Parameterbinding
Wanneer u objecten van de ene opdracht naar een andere opdracht doorsluist, probeert PowerShell de doorgesluisde objecten te koppelen aan een parameter van de ontvangende cmdlet.
Het onderdeel parameterbinding van PowerShell koppelt de invoerobjecten aan cmdlet-parameters op basis van de volgende criteria:
- De parameter moet invoer van een pijplijn accepteren.
- De parameter moet het type object accepteren dat wordt verzonden of een type dat kan worden geconverteerd naar het verwachte type.
- De parameter is niet gebruikt in de opdracht.
De cmdlet heeft bijvoorbeeld Start-Service
veel parameters, maar slechts twee van hen, Name en InputObject accepteren pijplijninvoer. De parameter Name gebruikt tekenreeksen en de parameter InputObject neemt serviceobjecten. Daarom kunt u tekenreeksen, serviceobjecten en objecten doorsluizen met eigenschappen die kunnen worden geconverteerd naar tekenreeks- of serviceobjecten.
PowerShell beheert parameterbinding zo efficiënt mogelijk. U kunt powershell niet voorstellen of dwingen om een binding met een specifieke parameter aan te gaan. De opdracht mislukt als PowerShell de objecten met pijpen niet kan binden.
Zie Pijplijnfouten onderzoeken verderop in dit artikel voor meer informatie over het oplossen van bindingsfouten.
Een-voor-een-verwerking
Het doorsturen van objecten naar een opdracht is vergelijkbaar met het gebruik van een parameter van de opdracht om de objecten te verzenden. Laten we eens kijken naar een voorbeeld van een pijplijn. In dit voorbeeld gebruiken we een pijplijn om een tabel met serviceobjecten weer te geven.
Get-Service | Format-Table -Property Name, DependentServices
Functioneel is dit vergelijkbaar met het gebruik van de InputObject-parameter van Format-Table
om de objectverzameling te verzenden.
We kunnen bijvoorbeeld de verzameling services opslaan in een variabele die wordt doorgegeven met behulp van de parameter InputObject .
$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices
Of we kunnen de opdracht insluiten in de parameter InputObject .
Format-Table -InputObject (Get-Service) -Property Name, DependentServices
Er is echter een belangrijk verschil. Wanneer u meerdere objecten doorstuurt naar een opdracht, worden de objecten door PowerShell één voor één naar de opdracht verzonden. Wanneer u een opdrachtparameter gebruikt, worden de objecten verzonden als één matrixobject. Dit kleine verschil heeft aanzienlijke gevolgen.
Bij het uitvoeren van een pijplijn inventariseert PowerShell automatisch elk type dat de interface of de IEnumerable
generieke tegenhanger implementeert. Geïnventareerde items worden één voor één via de pijplijn verzonden. PowerShell inventariseert ook System.Data.DataTable-typen via de Rows
eigenschap .
Er zijn enkele uitzonderingen op automatische inventarisatie.
- U moet de
GetEnumerator()
methode aanroepen voor hashtabellen, typen die de interface of deIDictionary
algemene tegenhanger implementeren en System.Xml. XmlNode-typen . - De klasse System.String implementeert , maar PowerShell inventariseert geen tekenreeksobjecten
IEnumerable
.
In de volgende voorbeelden worden een matrix en een hashtabel doorgesluisd naar de Measure-Object
cmdlet om het aantal objecten te tellen dat van de pijplijn is ontvangen. De matrix heeft meerdere leden en de hashtabel heeft meerdere sleutel-waardeparen. Alleen de matrix wordt één voor één geïnventariseerd.
@(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 :
Als u meerdere procesobjecten van de Get-Process
cmdlet doorstuurt naar de Get-Member
cmdlet, verzendt PowerShell elk procesobject één voor één naar Get-Member
. Get-Member
geeft de .NET-klasse (type) van de procesobjecten en hun eigenschappen en methoden weer.
Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize
...
Notitie
Get-Member
elimineert dubbele waarden, dus als de objecten allemaal van hetzelfde type zijn, wordt slechts één objecttype weergegeven.
Als u echter de parameter InputObject van Get-Member
gebruikt, Get-Member
ontvangt u een matrix met System.Diagnostics.Process-objecten als één eenheid. Hiermee worden de eigenschappen van een matrix met objecten weergegeven. (Let op het matrixsymbool ([]
) na de naam van het type System.Object .)
Bijvoorbeeld:
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()
...
Dit resultaat is mogelijk niet wat u bedoelde. Maar als u het begrijpt, kunt u het gebruiken. Alle matrixobjecten hebben bijvoorbeeld de eigenschap Count . U kunt dit gebruiken om het aantal processen te tellen dat op de computer wordt uitgevoerd.
Bijvoorbeeld:
(Get-Process).count
Het is belangrijk om te onthouden dat objecten die door de pijplijn worden verzonden, één voor één worden geleverd.
Systeemeigen opdrachten gebruiken in de pijplijn
Met PowerShell kunt u systeemeigen externe opdrachten opnemen in de pijplijn. Het is echter belangrijk te weten dat de pijplijn van PowerShell objectgeoriënteerd is en geen ondersteuning biedt voor onbewerkte bytegegevens.
Het doorsturen van uitvoer van een systeemeigen programma dat onbewerkte bytegegevens uitvoert, converteert de uitvoer naar .NET-tekenreeksen. Deze conversie kan leiden tot beschadiging van de uitvoer van onbewerkte gegevens.
Als tijdelijke oplossing roept u de systeemeigen opdrachten aan met behulp van cmd.exe /c
of sh -c
en het gebruik van de |
operators en >
van de systeemeigen shell.
Pijplijnfouten onderzoeken
Wanneer PowerShell de doorgesluisde objecten niet kan koppelen aan een parameter van de ontvangende cmdlet, mislukt de opdracht.
In het volgende voorbeeld proberen we een registervermelding van de ene registersleutel naar de andere te verplaatsen. De Get-Item
cmdlet haalt het doelpad op, dat vervolgens wordt doorgesluisd naar de Move-ItemProperty
cmdlet. Met Move-ItemProperty
de opdracht geeft u het huidige pad en de naam op van de registervermelding die moet worden verplaatst.
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
De opdracht mislukt en PowerShell geeft het volgende foutbericht weer:
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
Als u dit wilt onderzoeken, gebruikt u de Trace-Command
cmdlet om het parameterbindingsonderdeel van PowerShell te traceren. In het volgende voorbeeld wordt de parameterbinding bijhouden terwijl de pijplijn wordt uitgevoerd. De parameter PSHost geeft de traceringsresultaten weer in de console en de FilePath-parameter verzendt de traceringsresultaten naar het debug.txt
bestand voor later gebruik.
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
}
De resultaten van de tracering zijn lang, maar ze laten zien dat de waarden worden gebonden aan de Get-Item
cmdlet en vervolgens de benoemde waarden worden gebonden aan de Move-ItemProperty
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`]
...
Ten slotte ziet u dat de poging om het pad naar de doelparameter van Move-ItemProperty
te binden, is mislukt.
...
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
...
Gebruik de Get-Help
cmdlet om de kenmerken van de doelparameter weer te geven.
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
De resultaten laten zien dat doel alleen pijplijninvoer 'op eigenschapsnaam' gebruikt. Daarom moet het doorgesluisde object een eigenschap met de naam Bestemming hebben.
Gebruik Get-Member
om de eigenschappen weer te geven van het object dat afkomstig is van Get-Item
.
Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member
De uitvoer laat zien dat het item een Microsoft.Win32.RegistryKey-object is dat geen doeleigenschap heeft. Dit verklaart waarom de opdracht is mislukt.
De path parameter accepteert pijplijninvoer op naam of op waarde.
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
Om de opdracht op te lossen, moeten we de bestemming opgeven in de Move-ItemProperty
cmdlet en gebruiken Get-Item
om het pad op te halen van het item dat we willen verplaatsen.
Bijvoorbeeld:
Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product
Intrinsieke lijnvervolging
Zoals al is besproken, is een pijplijn een reeks opdrachten die zijn verbonden door pijplijnoperators (|
), meestal geschreven op één regel. Voor de leesbaarheid kunt u met PowerShell de pijplijn echter splitsen over meerdere regels. Wanneer een pipe-operator het laatste token op de regel is, voegt de PowerShell-parser de volgende regel toe aan de huidige opdracht om door te gaan met de constructie van de pijplijn.
Bijvoorbeeld de volgende pijplijn met één regel:
Command-1 | Command-2 | Command-3
kan worden geschreven als:
Command-1 |
Command-2 |
Command-3
De voorloopspaties op de volgende regels zijn niet significant. De inspringing verbetert de leesbaarheid.
PowerShell 7 voegt ondersteuning toe voor het vervolg van pijplijnen met het pijplijnteken aan het begin van een regel. In de volgende voorbeelden ziet u hoe u deze nieuwe functionaliteit kunt gebruiken.
# Wrapping with a pipe at the beginning of a line (no backtick required)
Get-Process | Where-Object CPU | Where-Object Path
| Get-Item | Where-Object FullName -match "AppData"
| Sort-Object FullName -Unique
# Wrapping with a pipe on a line by itself
Get-Process | Where-Object CPU | Where-Object Path
|
Get-Item | Where-Object FullName -match "AppData"
|
Sort-Object FullName -Unique
Belangrijk
Wanneer u interactief in de shell werkt, plakt u alleen code met pijplijnen aan het begin van een regel wanneer u Ctrl+V gebruikt om te plakken. Klik met de rechtermuisknop op plakbewerkingen en voeg de regels een voor een in. Omdat de regel niet eindigt op een pijplijnteken, wordt de invoer in PowerShell als voltooid beschouwd en wordt die regel uitgevoerd zoals deze is ingevoerd.