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 Command-1 die worden verzonden naar verzonden. Command-2 Command-2 verwerkt de objecten en verzendt deze naar Command-3 . Command-3 verwerkt de objecten en verzendt deze naar de pijplijn. Omdat er geen opdrachten meer in de pijplijn staan, 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 is een eenvoudig voorbeeld. Met de volgende opdracht wordt het Kladblok 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 vertegenwoordigt. Er wordt een pijplijnoperator ( ) gebruikt om het procesobject naar de | cmdlet te verzenden, waardoor het Stop-Process proces Kladblok gestopt. U ziet dat de opdracht geen naam- of id-parameter heeft om het proces op te geven, omdat het opgegeven proces via de Stop-Process pijplijn wordt verzonden.

In dit pijplijnvoorbeeld worden de tekstbestanden in de huidige map opgeslagen, 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-cmdlet doorseen naar een andere cmdlet van hetzelfde zelfstandig naamwoord. U kunt bijvoorbeeld de uitvoer van de Get-Service cmdlet doorsleesen naar de Start-Service Stop-Service cmdlets of .

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

Get-Service wmi | Start-Service

Voor een ander voorbeeld kunt u de uitvoer van of binnen de Get-Item Get-ChildItem PowerShell-registerprovider doorsleesen naar de New-ItemProperty cmdlet . In dit voorbeeld wordt een nieuwe registerinvoer, 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 hulpprogramma-cmdlets, zoals , , , en worden bijna Get-Member Where-Object uitsluitend gebruikt in Sort-Object Group-Object Measure-Object pijplijnen. U kunt elk objecttype doorspijpen naar deze cmdlets. In dit voorbeeld ziet u hoe u alle processen op de computer kunt sorteren op het aantal geopende grepen in elk proces.

Get-Process | Sort-Object -Property handles

U kunt objecten doorslingsen naar de opmaak-, export- en uitvoer-cmdlets, zoals Format-List , , , en Format-Table Export-Clixml Export-CSV 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 native opdrachten doorspreken 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 Geslaagd en Fout zijn vergelijkbaar met de stromen stdin en stderr van andere shells. Stdin is echter niet verbonden met de PowerShell-pijplijn voor invoer. Zie voor meer informatie about_Redirection.

Met een beetje oefening zult u merken dat het combineren van eenvoudige opdrachten in pijplijnen tijd en typen bespaart en uw scripts 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

Ter ondersteuning van pipelining moet de ontvangende cmdlet een parameter hebben die pijplijninvoer accepteert. Gebruik de opdracht met de opties Volledig of Parameter om te bepalen welke parameters van een Get-Help 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 verzendt, probeert PowerShell de objecten te koppelen aan de Start-Service parameters InputObject en Name.

Methoden voor het accepteren van pijplijninvoer

Cmdletsparameters kunnen pijplijninvoer op twee verschillende manieren accepteren:

  • ByValue: de parameter accepteert waarden die overeenkomen met het verwachte .NET-type of die naar dat type kunnen worden geconverteerd.

    De parameter Name van accepteert bijvoorbeeld Start-Service 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 heeft met dezelfde naam als de parameter .

    De parameter Name van kan bijvoorbeeld Start-Service objecten accepteren die een eigenschap Name hebben. Als u de eigenschappen van een object wilt weergeven, s pipet u het door naar Get-Member .

Sommige parameters kunnen objecten accepteren op waarde of eigenschapsnaam, waardoor het eenvoudiger is om invoer uit de pijplijn op te nemen.

Parameterbinding

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

Het parameterbindingonderdeel 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 veel parameters, maar slechts twee Start-Service parameters, Name en InputObject accepteren pijplijninvoer. De parameter Name heeft tekenreeksen en de parameter InputObject gebruikt serviceobjecten. Daarom kunt u tekenreeksen, serviceobjecten en objecten doorseen met eigenschappen die kunnen worden geconverteerd naar tekenreeks- of serviceobjecten.

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

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

Een-op-een-tijd-verwerking

Het doorspijpen van objecten naar een opdracht lijkt veel op het gebruik van een parameter van de opdracht om de objecten in te dienen. 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 gezien is dit hetzelfde als het gebruik van de parameter InputObject 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

We kunnen de opdracht ook insluiten in de parameter InputObject.

Format-Table -InputObject (Get-Service) -Property Name, DependentServices

Er is echter een belangrijk verschil. Wanneer u meerdere objecten doorspijpt 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.

Bij het uitvoeren van een pijplijn wordt in PowerShell automatisch elk type opsnoemd dat de interface implementeert en de leden één voor één via de IEnumerable pijplijn verzendt. De uitzondering is [hashtable] , waarvoor een aanroep naar de methode is GetEnumerator() vereist.

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

@(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 cmdlet naar de cmdlet doorst pipet, verzendt PowerShell elk procesobject één voor één Get-Process Get-Member naar Get-Member . Get-Member geeft de .NET-klasse (type) van de procesobjecten en de 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 van hetzelfde type zijn, wordt slechts één objecttype weergegeven.

Als u echter de parameter InputObject van gebruikt, ontvangt u een matrix van Get-Member Get-Member System.Diagnostics.Process-objecten als één eenheid. De eigenschappen van een matrix met objecten worden 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 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.

Pijplijnfouten onderzoeken

Wanneer PowerShell de doorsleesobjecten niet kan koppelen aan een parameter van de ontvangende cmdlet, mislukt de opdracht.

In het volgende voorbeeld proberen we een registerinvoer van de ene registersleutel naar de andere te verplaatsen. De Get-Item cmdlet haalt het doelpad op, dat vervolgens wordt doorspijpt naar de Move-ItemProperty cmdlet . Met Move-ItemProperty de opdracht geeft u het huidige pad en de naam op van de registerinvoer 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, Trace-Command gebruikt u de cmdlet om het parameterbindingsonderdeel van PowerShell te traceren. In het volgende voorbeeld wordt de parameterbinding bij de uitvoering van de pijplijn traceringen. De PSHost parameter geeft de traceerresultaten in de console en de FilePath parameter verzenden de traceerresultaten naar het debug.txt bestand voor latere referentie.

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 trace zijn lang, maar ze tonen de waarden die worden gebonden aan de cmdlet en vervolgens de benoemde waarden die worden gebonden Get-Item 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 binden aan de parameter Destination van Move-ItemProperty 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 parameter Destination 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 geven aan dat Bestemming alleen pijplijninvoer 'op eigenschapsnaam' gebruikt. Daarom moet het piped-object een eigenschap hebben met de naam Destination.

Gebruik Get-Member om de eigenschappen van het object te zien die afkomstig zijn van 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 doel-eigenschap heeft. Dit 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 het doel opgeven in de cmdlet en gebruiken om het pad op te halen van het Move-ItemProperty item dat we willen Get-Item verplaatsen.

Bijvoorbeeld:

Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product

Intrinsieke lijnverdring

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 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 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 vooraanstaande spaties 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. Met de rechtermuisknop op plakken bewerkingen invoegen van de regels een voor een. Omdat de regel niet eindigt met een pijplijnteken, wordt de invoer in PowerShell als voltooid gezien en wordt die regel uitgevoerd zoals ingevoerd.

Zie ook

about_PSReadLine

about_Objects

about_Parameters

about_Command_Syntax

about_ForEach