De PowerShell-pijplijn is een van de belangrijkste (en handigste) functies van de PowerShell-shell en scripttaal. Zodra je de basisprincipes begrijpt van hoe het werkt en wat het kan, kun je de kracht ervan benutten in je eigen functies. In deze tutorial ga je dat precies doen!
De PowerShell-pijplijn stelt je in staat om commando’s aan elkaar te koppelen om een enkele ‘pijplijn’ te bouwen, wat de code vereenvoudigt, parallelle verwerking mogelijk maakt en meer. Als je klaar bent om meer te leren over de pijplijn en je eigen functies te bouwen om er gebruik van te maken, laten we dan beginnen!
Vereisten
Deze post zal een tutorial zijn en zal volledig bestaan uit praktijkdemonstraties. Als je wilt meedoen, heb je PowerShell v3+ nodig. Deze tutorial zal gebruikmaken van Windows PowerShell v5.1.
Begrip van de PowerShell-pijplijn
De meeste PowerShell-commando’s ontvangen invoer via een parameter. Het commando ontvangt een object als invoer en doet er iets mee. Vervolgens geeft het optioneel een object terug via de uitvoer.
Commando’s in een pijplijn gedragen zich als menselijke lopers in een estafetteloop. Elke loper in de race, behalve de eerste en de laatste, neemt de estafettestok (objecten) over van zijn voorganger en geeft het door aan de volgende.
Bijvoorbeeld, de Stop-Service
cmdlet heeft een parameter genaamd InputObject
. Met deze parameter kunt u een specifiek type object doorgeven aan Stop-Service
dat de Windows-service vertegenwoordigt die u wilt stoppen.
Om de InputObject
-parameter te gebruiken, kunt u het service-object ophalen via Get-Service
en vervolgens het object doorgeven aan de InputObject
-parameter zoals hieronder getoond. Deze methode om invoer te verstrekken aan de Stop-Service
cmdlet via de InputObject
-parameter werkt uitstekend en krijgt het werk gedaan.
Deze methode om invoer door te geven aan de Stop-Service
-opdracht vereist twee afzonderlijke stappen. PowerShell moet eerst Get-Service
uitvoeren, de uitvoer opslaan in een variabele en vervolgens die waarde doorgeven aan Stop-Service
via de InputObject
-parameter.
Nu, vergelijk het bovenstaande fragment met het onderstaande fragment, dat hetzelfde doet. Het is veel eenvoudiger omdat u geen $services
-variabele hoeft te maken of zelfs helemaal geen gebruik hoeft te maken van de InputObject
-parameter. In plaats daarvan “weet” PowerShell dat u van plan bent de InputObject
-parameter te gebruiken. Dit gebeurt via een concept dat parameterbinding wordt genoemd.
U hebt nu opdrachten aan elkaar “gekoppeld” met de |
-operator. U hebt een pijplijn gemaakt.
Maar u hoeft niet alleen twee opdrachten te gebruiken om een pijplijn te maken; u kunt er zoveel aan elkaar koppelen als u wilt (als de opdrachtparameters dit ondersteunen). Bijvoorbeeld, het onderstaande codefragment:
- Voert alle objecten door die de
Get-Service
cmdlet retourneert naar deWhere-Object
cmdlet. - De
Where-Object
cmdlet bekijkt vervolgens deStatus
-eigenschap van elk object en retourneert alleen die objecten met een waarde vanRunning
. - Vervolgens worden al die objecten doorgestuurd naar
Select-Object
, die alleen deName
– enDisplayName
-eigenschappen van de objecten retourneert. - Aangezien geen andere cmdlet de objecten accepteert die
Select-Object
uitvoert, retourneert de opdracht de objecten rechtstreeks naar de console.
De cmdlets
Where-Object
enSelect-Object
begrijpen hoe ze de invoer via de pijplijn moeten verwerken door een concept genaamd parameterbinding, besproken in de volgende sectie.
Voor aanvullende informatie over pijplijnen, voer het commando
Get-Help about_pipelines
uit.
Pijplijn Parameter Binding
Op het eerste gezicht lijkt de pijplijn triviaal. Per slot van rekening geeft het alleen objecten door van de ene opdracht naar de andere. Maar in werkelijkheid is de pijplijn veel ingewikkelder. Opdrachten accepteren alleen invoer via parameters. De pijplijn moet op de een of andere manier bepalen welke parameter moet worden gebruikt, zelfs wanneer je deze niet expliciet definieert.
De taak om uit te zoeken welke parameter te gebruiken wanneer een opdracht invoer via de pijplijn ontvangt, staat bekend als parameterbinding. Om succesvol een object dat binnenkomt via de pijplijn aan een parameter te binden, moeten de parameter(s) van de binnenkomende opdracht dit ondersteunen. Commandopdrachten ondersteunen parameterbinding via de pijplijn op een van twee manieren; ByValue
en/of ByPropertyName
.
ByValue
De opdrachtparameter accepteert het volledige binnenkomende object als de parameterwaarde. Een ByValue
-parameter zoekt naar een object van een specifiek type in binnenkomende objecten. Als dat objecttype overeenkomt, gaat PowerShell ervan uit dat het object aan die parameter moet worden gebonden en accepteert het.
De
Get-ChildItem
-cmdlet heeft een parameter genaamdPath
die een stringobjecttype accepteert en invoer via de pijplijn viaByValue
. Hierdoor retourneert iets als'C:\Windows' | Get-ChildItem
alle bestanden in de map C:\Windows omdatC:\Windows
een string is.
ByPropertyName
De opdrachtparameter accepteert geen volledig object maar een enkele eigenschap van dat object. Dit doet het niet door naar het objecttype te kijken, maar naar de eigenschapsnaam.
De
Get-Process
cmdlet heeft eenName
-parameter die is ingesteld om pijplijninvoer te accepterenByPropertyName
. Wanneer u een object met eenName
-eigenschap doorgeeft aan deGet-Process
cmdlet zoals[pscustomobject]@{Name='firefox'} | Get-Process
, koppelt PowerShell deName
-eigenschap van het binnenkomende object aan deName
-parameter en gebruikt die waarde.
Het ontdekken van commandoparameters die de pijplijn ondersteunen
Zoals eerder vermeld, ondersteunt niet elk commando pijplijninvoer. De commando-auteur moet die functionaliteit ontwikkelen. Het commando moet ten minste één parameter hebben die de pijplijn ondersteunt, zet ByValue
of ByPropertyName
.
Hoe weet u welke commando’s en hun parameters pijplijninvoer ondersteunen? U kunt het gewoon proberen met trial and error, maar er is een betere manier met behulp van het PowerShell help systeem met het Get-Help
commando.
Bijvoorbeeld, kijk eens naar de Get-ChildItem
cmdlet’s parameter Path
hieronder. U kunt zien dat het beide soorten pijplijninvoer ondersteunt.

Eenmaal je weet welke commandoparameters pijplijninvoer ondersteunen, kun je vervolgens van die functionaliteit profiteren, zoals hieronder wordt getoond.
Maar, aan de andere kant, ondersteunt de parameter DisplayName
op Get-Service
geen invoer via de pijplijn.

Het opbouwen van je eigen pijplijnfunctie
Hoewel de standaard PowerShell-cmdlets invoer via de pijplijn ondersteunen, betekent dit niet dat je geen gebruik kunt maken van die functionaliteit. Gelukkig kun je ook functies bouwen die invoer via de pijplijn accepteren.
Om dit te demonstreren, laten we beginnen met een bestaande functie genaamd Get-ConnectionStatus
.
- Deze functie heeft een enkele parameter (die geen invoer via de pijplijn accepteert) genaamd
ComputerName
, waarmee je één of meer strings aan het doorgeven bent. Je kunt zien dat de parameterComputerName
geen invoer via de pijplijn accepteert omdat deze niet is gedefinieerd als een parameterattribuut ([Parameter()]
). - Vervolgens leest de functie elk van die strings en voert de
Test-Connection
-cmdlet uit tegen elk ervan. - Voor elke doorgegeven computer naam retourneert het vervolgens een object met een
ComputerName
enStatus
eigenschap.
Vervolgens roept u de Get-ConnectionStatus
aan door de ComputerName
parameter één of meer hostnamen of IP-adressen door te geven zoals hieronder.
Stap 1: Pipeline invoer toestaan
Om deze functie in staat te stellen pipeline invoer te accepteren, moet u eerst het juiste parameterattribuut definiëren. Dit attribuut kan ofwel ValueFromPipeline
zijn om pipeline invoer ByValue te accepteren, of ValueFromPipelineByPropertyName
om pipeline invoer ByPropertyName te accepteren.
Voor dit voorbeeld voegt u het ValueFromPipeline
parameterattribuut toe binnen de haken van de [Parameter()]
definitie zoals hieronder getoond.
Op dit punt is dat technisch gezien alles wat je moet doen. De Get-ConnectionStatus
functie zal nu elk doorgegeven stringobject binden aan de ComputerName
parameter. Maar, zelfs als parameterbinding plaatsvindt, betekent dit niet dat de functie er iets zinvols mee zal doen.
Stap 2: Een Process-blok toevoegen
Wanneer u wilt dat PowerShell alle objecten verwerkt die binnenkomen via de pipeline, moet u vervolgens een Process
blok toevoegen. Dit blok vertelt PowerShell om elk object dat binnenkomt via de pipeline te verwerken.
Zonder een
Process
blok zal PowerShell alleen het eerste object verwerken dat uit de pipeline komt. HetProcess
blok vertelt PowerShell om door te gaan met het verwerken van objecten.
Voeg een Process
-blok toe zoals hieronder weergegeven door alle functionaliteit van de functie erin te omvatten.
Stuur altijd uitvoer vanuit het
Process
-blok. Het verzenden van uitvoer vanuit hetProcess
-blok “stroomt” de objecten uit naar de pijplijn, zodat andere commando’s die objecten vanuit de pijplijn kunnen accepteren.
Het doorgeven van objecten aan de PowerShell-pijplijn
Zodra je een Process
-blok hebt gedefinieerd in de functie hierboven, kun je nu de functie oproepen door waarden door te geven aan de parameter ComputerName
via de pijplijn zoals hieronder weergegeven.
Op dit punt kun je echt profiteren van de kracht van de pijplijn en beginnen met het opnemen van meer commando’s in de mix. Bijvoorbeeld, misschien heb je een tekstbestand, C:\Test\computers.txt, met een regel IP-adressen gescheiden door een nieuwe regel zoals hieronder.
Je zou dan de Get-Content
-cmdlet kunnen gebruiken om elk van die IP-adressen in het tekstbestand te lezen en ze rechtstreeks door te geven aan de functie Get-ConnectionStatus
.
Door deze configuratie nog een stap verder te nemen, zou je de objecten die Get-ConnectionStatus
retourneert rechtstreeks naar de ForEach-Object
-cmdlet kunnen leiden.
De code hieronder:
- Leest alle computernamen in het tekstbestand en geeft ze door aan de functie
Get-ConnectionStatus
. -
Get-ConnectionStatus
verwerkt elke computernaam en retourneert een object met de eigenschappenComputerName
enStatus
. -
Get-ConnectionStatus
geeft vervolgens elk object door aan de cmdletForEach-Object
, die dan een enkele string retourneert gekleurd als Cyan met een menselijk leesbare status.
Als pijplijninvoer niet was ingeschakeld op de parameter
ComputerName
of alsGet-ConnectionStatus
geen object retourneerde binnen hetProcess
-blok, zou PowerShell geen status naar de console retourneren totdat alle objecten (IP-adressen) zijn verwerkt.
Pijplijnbinding op eigenschapsnaam
Tot nu toe is de cmdlet Get-ConnectionStatus
ingesteld om pijplijninvoer per waarde te accepteren (ValueFromPipeline
) door een array van strings zoals '127.0.0.1', '192.168.1.100'
te accepteren. Zou deze functie ook werken zoals verwacht als de invoer afkomstig was van een CSV-bestand in plaats van een tekstbestand met IP-adressen?
Misschien hebt u een CSV-bestand dat er als volgt uitziet op C:\Test\pc-list.csv.
Merk op dat het veld
ComputerName
in het CSV-bestand dezelfde naam heeft als deComputerName
-parameter vanGet-ConnectionStatus
.
Als u zou proberen het CSV-bestand te importeren en door te geven via de pijplijn naar Get-ConnectionStatus
, retourneert de functie een onverwacht resultaat in de kolom ComputerName
.
Kun je raden wat er misging? Immers, de parameter naam komt overeen, dus waarom bond de PowerShell-pijplijn de output die Import-CSV
terugkeerde niet aan de ComputerName
-parameter op Get-ConnectionStatus
? Omdat je het parameterattribuut ValueFromPipelineByPropertyName
nodig hebt.
Vanaf dit moment heeft de ComputerName
-parameter van de functie een parameterdefinitie die er zo uitziet [Parameter(ValueFromPipeline)]
. Daarom moet je ValueFromPipelineByPropertyName
toevoegen om de ComputerName
-parameter in te stellen om invoer via eigenschapsnaam te ondersteunen, zoals hieronder wordt getoond.
Zodra je pijplijnondersteuning hebt via ByPropertyName, vertel je PowerShell om te beginnen met het kijken naar de objecteigenschapnamen en het objecttype. Nadat je deze wijziging hebt aangebracht, zou je de verwachte output moeten zien.
Samenvatting
In deze zelfstudie heb je geleerd hoe de PowerShell-pijplijn werkt, hoe het parameters bindt, en zelfs hoe je je eigen functie kunt maken die de PowerShell-pijplijn ondersteunt.
Hoewel functies zonder de pijplijn zullen werken, zullen ze geen objecten “streamen” van het ene commando naar het andere en de code niet vereenvoudigen.
Kun je nadenken over een functie die je hebt geschreven, of misschien gaat schrijven, die baat kan hebben bij het gereed maken voor de pijplijn?