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 naar 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, verzonden naar Command-2. Command-2 verwerkt de objecten en verzendt deze naar Command-3. Command-3 verwerkt de objecten en verzendt ze omlaag in de pijplijn. Omdat er geen opdrachten meer in de pijplijn staan, worden de resultaten weergegeven in de console.

In een pijplijn worden de opdrachten verwerkt in volgorde van links naar rechts. De verwerking wordt verwerkt als één bewerking en 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- ofid-parameter heeft om het proces op te geven, omdat het opgegeven proces wordt verzonden via de pijplijn.

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 terwijl 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-cmdletdoorsluisen naar een andere cmdlet van hetzelfde zelfstandig naamwoord. U kunt bijvoorbeeld de uitvoer van de Get-Service cmdlet doorsluizen naar de Start-Service of Stop-Service cmdlets.

Met deze voorbeeldpijplijn wordt de WMI-service op de computer gestart:

Get-Service wmi | Start-Service

U kunt bijvoorbeeld de uitvoer van of Get-ChildItem binnen de PowerShell-registerprovider doorsluisen Get-Item naar de New-ItemProperty cmdlet. In dit voorbeeld wordt een nieuwe registervermelding , NoOfEmployees, met een waarde van 8124, toegevoegd aan de registersleutel MyCompany .

Get-Item -Path HKLM:\Software\MyCompany |
  New-ItemProperty -Name NoOfEmployees -Value 8124

Veel van de hulpprogramma-cmdlets, zoals Get-Member, Where-Object, Sort-Objecten Group-ObjectMeasure-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 doorsluisen naar de cmdlets voor opmaak, export en uitvoer, zoals Format-List, Export-ClixmlFormat-Table, , , en . Export-CSVOut-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 doorsluisen 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 succes- en foutstromen zijn vergelijkbaar met de stdin- en stderr-stromen van andere shells. Stdin is echter niet verbonden met de PowerShell-pijplijn voor invoer. Zie about_Redirection voor meer informatie.

Met wat oefening vindt u dat het combineren van eenvoudige opdrachten in pijplijnen tijd en typen bespaart en het efficiënter maken van uw scripting.

Hoe pijplijnen werken

In deze sectie wordt uitgelegd hoe invoerobjecten zijn gebonden aan cmdlet-parameters en worden verwerkt tijdens het uitvoeren van de pijplijn.

Pijplijninvoer accepteren

Ter ondersteuning van pipelining 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 *

In de help voor de Start-Service cmdlet ziet u 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 Start-Serviceverzendt, 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 naamparameter van Start-Service accepteert bijvoorbeeld pijplijninvoer op waarde. Het kan tekenreeksobjecten of objecten accepteren die kunnen worden geconverteerd naar tekenreeksen.

  • ByPropertyName: De parameter accepteert alleen invoer wanneer het invoerobject een eigenschap van dezelfde naam heeft als de parameter.

    De parameter Name van Start-Service kan bijvoorbeeld objecten met een eigenschap Name accepteren. Als u de eigenschappen van een object wilt weergeven, sluist u het naar Get-Member.

Sommige parameters kunnen objecten accepteren op basis van de waarde- of eigenschapsnaam, zodat u gemakkelijker invoer uit de pijplijn kunt nemen.

Parameterbinding

Wanneer u objecten van de ene opdracht naar een andere opdracht sluist, probeert PowerShell de gesluisde objecten te koppelen aan een parameter van de ontvangende cmdlet.

Het parameterbindingsonderdeel van PowerShell koppelt de invoerobjecten aan cmdlet-parameters volgens 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 Start-Service cmdlet heeft bijvoorbeeld veel parameters, maar slechts twee parameters, Naam en InputObject accepteren pijplijninvoer. De parameter Name neemt tekenreeksen en de parameter InputObject neemt serviceobjecten. Daarom kunt u tekenreeksen, serviceobjecten en objecten pijpen met eigenschappen die kunnen worden geconverteerd naar tekenreeks- of serviceobjecten.

PowerShell beheert parameterbinding zo efficiënt mogelijk. U kunt PowerShell niet voorstellen of forceren om verbinding te maken met een specifieke parameter. De opdracht mislukt als PowerShell de gesluisde objecten niet kan binden.

Zie Pijplijnfouten onderzoeken verderop in dit artikel voor meer informatie over het oplossen van bindingsfouten .

Eenmalige verwerking

Piping-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 parameter InputObject van het verzenden van Format-Table de objectverzameling.

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, verzendt PowerShell de objecten één voor één naar de opdracht. Wanneer u een opdrachtparameter gebruikt, worden de objecten verzonden als één matrixobject. Dit kleine verschil heeft aanzienlijke gevolgen.

Wanneer u een pijplijn uitvoert, inventariseert PowerShell automatisch elk type dat de IEnumerable interface implementeert en verzendt de leden één voor één via de pijplijn. De uitzondering is [hashtable], waarvoor een aanroep naar de GetEnumerator() methode is vereist.

In de volgende voorbeelden worden een matrix en een hashtabel doorgesluisd naar de Measure-Object cmdlet om het aantal objecten te tellen dat is ontvangen van de pijplijn. De matrix heeft meerdere leden en de hashtabel heeft meerdere sleutel-waardeparen. Alleen de matrix wordt één voor één opgesomd.

@(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 naar de Get-Member cmdlet doorstuurt, verzendt PowerShell elk procesobject, één voor één, naar Get-Member. Get-Member geeft de .NET-klasse (type) van de procesobjecten en de bijbehorende 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 duplicaten, dus als de objecten allemaal hetzelfde type zijn, wordt slechts één objecttype weergegeven.

Als u echter de parameter InputObject van Get-Membergebruikt, ontvangt u Get-Member een matrix van System.Diagnostics.Process-objecten als één eenheid. Hiermee worden de eigenschappen van een matrix met objecten weergegeven. (Noteer 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 nadat 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 naar 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 om te weten dat de pijplijn van PowerShell objectgeoriënteerd is en geen ondersteuning biedt voor onbewerkte bytegegevens.

Doorsturen of omleiden 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 cmd.exe /c behulp van of sh -c en het gebruik van de | en > operators van de systeemeigen shell.

Pijplijnfouten onderzoeken

Als PowerShell de gesluisde 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. Het volgende voorbeeld traceert parameterbinding terwijl de pijplijn wordt uitgevoerd. De PSHost-parameter 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 tonen de waarden die zijn gebonden aan de Get-Item cmdlet en vervolgens de benoemde waarden die zijn 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 te verbinden met de doelparameter mislukt Move-ItemProperty .

...
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 parameter Doel 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 gesluisde object een eigenschap met de naam Destination hebben.

Gebruik Get-Member dit bestand om de eigenschappen van het object te bekijken.Get-Item

Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member

In de uitvoer ziet u dat het item een Microsoft.Win32.RegistryKey-object is dat geen doeleigenschap heeft. Dat verklaart waarom de opdracht is mislukt.

De parameter Path 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 leesbaarheid kunt u echter met PowerShell de pijplijn op meerdere regels splitsen. Wanneer een pijpoperator 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 bouw 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 code met pijplijnen aan het begin van een regel alleen wanneer u Ctrl+V gebruikt om te plakken. Klik met de rechtermuisknop op plakbewerkingen om de regels één voor één in te voegen. Omdat de regel niet eindigt op een pijplijnteken, wordt in PowerShell de invoer als voltooid beschouwd en wordt die regel uitgevoerd zoals opgegeven.

Zie ook