Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Krátký popis
Kombinování příkazů do kanálů v PowerShellu
Dlouhý popis
Roura je série příkazů propojených operátory rourového spojení (|) (ASCII 124). Každý operátor potrubí odešle výsledky předchozího příkazu do dalšího příkazu.
Výstup prvního příkazu lze odeslat ke zpracování jako vstup do druhého příkazu. A tento výstup lze odeslat do dalšího příkazu. Výsledkem je složitý řetězec příkazů nebo kanál, který se skládá z řady jednoduchých příkazů.
Příklad:
Command-1 | Command-2 | Command-3
V tomto příkladu jsou objekty, které Command-1 generují, odeslány do Command-2.
Command-2 zpracovává objekty a odesílá je do Command-3.
Command-3 zpracovává objekty a odesílá je do kanálu. Nejsou-li v zásobníku příkazů žádné další příkazy, výsledky se zobrazí na konzoli.
V pipeline se příkazy zpracovávají v pořadí zleva doprava. Zpracování se zpracovává jako jedna operace a výstup se zobrazí při vygenerování.
Tady je jednoduchý příklad. Následující příkaz získá proces Poznámkového bloku a pak ho zastaví.
Příklad:
Get-Process notepad | Stop-Process
První příkaz používá rutinu Get-Process k získání objektu představujícího proces Poznámkového bloku. Používá operátor kanálu (|) k odeslání objektu procesu do cmdletu Stop-Process, který zastaví proces programu Poznámkový blok. Všimněte si, že příkaz Stop-Process nemá parametr Název nebo ID k určení procesu, protože zadaný proces se odešle prostřednictvím potrubí.
Tento příklad kanálu získá textové soubory v aktuálním adresáři, vybere pouze soubory, které jsou delší než 10 000 bajtů, seřadí je podle délky a zobrazí název a délku každého souboru v tabulce.
Get-ChildItem -Path *.txt |
Where-Object {$_.length -gt 10000} |
Sort-Object -Property length |
Format-Table -Property name, length
Tento kanál se skládá ze čtyř příkazů v zadaném pořadí. Následující obrázek znázorňuje výstup z každého příkazu, který se předá dalšímu příkazu po něm v rouře.
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
Použití kanálů
Většina rutin PowerShellu je navržená tak, aby podporovala kanály. Ve většině případů můžete přenést výsledky cmdletu Get do jiného cmdletu stejného typu.
Výstup rutiny Get-Service můžete například přesměrovat do rutin Start-Service nebo Stop-Service.
Tento ukázkový proces spustí službu WMI v počítači:
Get-Service wmi | Start-Service
V jiném příkladu můžete výstup Get-Item nebo Get-ChildItem v rámci poskytovatele registru PowerShellu převést na rutinu New-ItemProperty. Tento příklad přidá novou položku registru, NoOfEmployees, s hodnotou 8124, do MyCompany klíč registru.
Get-Item -Path HKLM:\Software\MyCompany |
New-ItemProperty -Name NoOfEmployees -Value 8124
Mnoho rutin nástrojů, jako jsou například Get-Member, Where-Object, Sort-Object, Group-Objecta Measure-Object, se používají téměř výhradně v kanálech. K těmto cmdletům můžete přesměrovat libovolný typ objektu. Tento příklad ukazuje, jak seřadit všechny procesy na počítači podle počtu otevřených popisovačů v každém procesu.
Get-Process | Sort-Object -Property handles
Objekty můžete pipetovat do rutin formátování, exportu a výstupu, jako jsou Format-List, Format-Table, Export-Clixml, Export-CSVa Out-File.
Tento příklad ukazuje, jak pomocí rutiny Format-List zobrazit seznam vlastností objektu procesu.
Get-Process winlogon | Format-List -Property *
Výstup nativních příkazů můžete také směrovat do cmdletů PowerShellu. Například:
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
Důležité
Datové proudy Success a Error jsou podobné proudům stdin a stderr v jiných shellových prostředích. Stdin se ale ke vstupnímu kanálu PowerShellu nepřipojí. Pro více informací se podívejte na about_Redirection.
S trochou praxe zjistíte, že kombinování jednoduchých příkazů do potrubí šetří čas a usnadňuje psaní, čímž zefektivňuje skriptování.
Jak fungují kanály
Tato část vysvětluje, jak jsou vstupní objekty svázány s parametry cmdletu a zpracovány během provádění kanálu.
Přijímá vstup z rozvodného potrubí.
Aby bylo možné kanálování podporovat, musí mít přijímající rutina parametr, který přijímá vstup kanálu. Pomocí příkazu Get-Help s možnostmi Full nebo Parameter určete, které parametry příkazového modulu přijímají vstup z roury.
Například pokud chcete určit, které parametry příkazu Start-Service přijímají vstup z kanálu, zadejte:
Get-Help Start-Service -Full
nebo
Get-Help Start-Service -Parameter *
Nápověda pro rutinu Start-Service ukazuje, že pouze parametry InputObject a Name přijímají vstup z kanálu.
-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
Když odesíláte objekty skrze kanál do
Metody přijímání vstupu kanálu
Parametry cmdletů mohou přijímat vstup datového proudu jedním ze dvou různých způsobů:
ByValue: Parametr přijímá hodnoty, které odpovídají očekávanému typu .NET nebo které lze převést na tento typ.
Například parametr Název
Start-Servicepřijímá vstup z kanálu jako hodnotu. Může přijímat objekty řetězců nebo objekty, které lze převést na řetězce.ByPropertyName: Parametr přijímá vstup pouze v případech, kdy vstupní objekt má vlastnost se stejným názvem jako parametr.
Například parametr Name
Start-Servicemůže přijímat objekty, které mají vlastnost Name. Chcete-li zobrazit seznam vlastností objektu, předejte jej pomocí roury doGet-Member.
Některé parametry mohou přijímat objekty podle hodnoty nebo názvu vlastnosti, což usnadňuje příjem vstupu z kanálu.
Přiřazení parametrů
Když objekty předáte z jednoho příkazu do jiného příkazu, PowerShell se pokusí přidružit předané objekty k parametru přijímajícího cmdletu.
Komponenta vazby parametrů PowerShellu přidruží vstupní objekty k parametrům rutiny podle následujících kritérií:
- Parametr musí přijímat vstupy z kanálu.
- Parametr musí přijmout typ odesílaného objektu nebo typ, který lze převést na očekávaný typ.
- Parametr nebyl použit v příkazu.
Například rutina Start-Service má mnoho parametrů, ale pouze dva z nich, Název a InputObject přijímají vstup z kanálu. Parametr Name přebírá řetězce a parametr InputObject přebírá objekty služby. Proto můžete používat řetězce, servisní objekty a objekty s vlastnostmi, které lze převést na řetězce nebo servisní objekty.
PowerShell spravuje vazbu parametrů co nejefektivněji. PowerShell nemůže navrhnout nebo vynutit vytvoření vazby ke konkrétnímu parametru. Příkaz selže, pokud PowerShell nemůže navázat objekty přenesené potrubím.
Další informace o řešení chyb vazby najdete v tématu Zkoumání chyb kanálu dále v tomto článku.
Jednorázové zpracování
Piping objektů do příkazu je mnohem podobné použití parametru příkazu k odeslání objektů. Podívejme se na příklad kanálu. V tomto příkladu používáme kanál k zobrazení tabulky objektů služby.
Get-Service | Format-Table -Property Name, DependentServices
Funkčně se to podobá použití parametru InputObjectFormat-Table k odeslání kolekce objektů.
Kolekci služeb můžeme například uložit do proměnné předané pomocí parametru InputObject.
$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices
Nebo můžeme příkaz vložit do parametru InputObject.
Format-Table -InputObject (Get-Service) -Property Name, DependentServices
Je ale důležitý rozdíl. Když předáte více objektů do příkazu, PowerShell odešle objekty do příkazu po jednom. Při použití parametru příkazu se objekty odesílají jako jeden maticový objekt. Tento malý rozdíl má významné důsledky.
Při spouštění potrubí PowerShell automaticky prochází libovolné typy, které implementují rozhraní IEnumerable nebo jeho obecný protějšek. Výčtové položky se posílají potrubím po jedné. PowerShell také vyčísluje typy System.Data.DataTable prostřednictvím vlastnosti Rows.
Existuje několik výjimek automatického výčtu.
- Musíte volat metodu
GetEnumerator()pro hašovací tabulky, typy, které implementují rozhraníIDictionarynebo jeho obecný protějšek, a typy System.Xml.XmlNode. - Třída System.String implementuje
IEnumerable, ale PowerShell nevypíše objekty řetězců.
V následujících příkladech se pole a hashovací tabulka předávají do rutiny Measure-Object, aby spočítaly počet objektů přijatých z potrubí. Pole má více členů a hashovatelná tabulka má několik párů klíč-hodnota. Pouze pole se vyčíslí po jednom.
@(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 :
Podobně pokud předáte více objektů procesu z Get-Process rutiny do rutiny Get-Member, PowerShell odešle každý objekt procesu postupně do Get-Member.
Get-Member zobrazí třídu .NET (typ) objektů procesu a jejich vlastnosti a metody.
Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize
...
Poznámka:
Get-Member eliminuje duplicity, takže pokud jsou všechny objekty stejného typu, zobrazí se pouze jeden typ objektu.
Pokud však použijete parametr InputObject u Get-Member, Get-Member obdrží pole objektů System.Diagnostics.Process jako jeden celek. Zobrazí vlastnosti pole objektů. (Poznamenejte si symbol pole ([]) za názvem typu System.Object.)
Příklad:
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()
...
Tento výsledek nemusí být tím, co jste chtěli. Ale až to pochopíte, můžete ho použít. Například všechny objekty pole mají vlastnost Count. Můžete ho použít ke spočítání počtu procesů spuštěných v počítači.
Příklad:
(Get-Process).count
Je důležité si uvědomit, že objekty odeslané kanálem se doručují po jednom.
Použití nativních příkazů v potrubí
PowerShell umožňuje zahrnout do kanálu nativní externí příkazy. Je ale důležité si uvědomit, že kanál PowerShellu je objektově orientovaný a nepodporuje nezpracovaná bajtová data.
Předávání k danému cíli nebo přesměrování výstupu z nativního programu, který generuje surová bajtová data, převádí tento výstup na .NET řetězce. Tento převod může způsobit poškození nezpracovaného výstupu dat.
Jako alternativní řešení volejte nativní příkazy pomocí cmd.exe /c operátorů or sh -c a pomocí operátorů | a > poskytovaných nativním prostředím.
Zkoumání chyb v potrubí
Pokud PowerShell nemůže přidružit objekty s parametrem přijímajícího cmdletu, příkaz selže.
V následujícím příkladu se pokusíme přesunout položku registru z jednoho klíče registru do jiného. Rutina Get-Item získá cílovou cestu, která se pak předá rutině Move-ItemProperty. Příkaz Move-ItemProperty určuje aktuální cestu a název položky registru, která se má přesunout.
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
Příkaz selže a PowerShell zobrazí následující chybovou zprávu:
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
K prošetření použijte rutinu Trace-Command ke sledování komponenty vazby parametrů PowerShellu. Následující příklad sleduje vázání parametrů během běhu kanálu. Parametr PSHost zobrazí výsledky trasování v konzole a parametr FilePath odešle výsledky trasování do souboru debug.txt pro pozdější referenci.
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
}
Výsledky trasování jsou zdlouhavé, ale ukazují hodnoty, které jsou vázány na cmdlet Get-Item, a poté pojmenované hodnoty, které jsou vázány na cmdlet Move-ItemProperty.
...
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`]
...
Nakonec ukazuje, že pokus o vytvoření vazby cesty k parametru DestinationMove-ItemProperty selhal.
...
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
...
Pomocí rutiny Get-Help zobrazte atributy 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
Výsledky ukazují, že Destination přijímá vstup kanálu pouze "podle názvu vlastnosti". Proto musí mít objekt typu rourkový vlastnost s názvem Destination.
Pomocí Get-Member zobrazíte vlastnosti objektu pocházejícího z Get-Item.
Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member
Výstup ukazuje, že položka je Microsoft.Win32.RegistryKey objekt, který nemá vlastnost Destination. To vysvětluje, proč příkaz selhal.
Parametr Path přijímá vstup kanálu podle názvu nebo hodnoty.
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
Pokud chcete příkaz opravit, musíme zadat cíl v rutině Move-ItemProperty a pomocí Get-Item získat cestu položky, kterou chceme přesunout.
Příklad:
Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product
Pokračování vnitřní čáry
Jak už bylo popsáno, kanál je řada příkazů propojených operátory kanálu (|), obvykle napsané na jednom řádku. Kvůli čitelnosti ale PowerShell umožňuje rozdělit kanál mezi více řádků. Pokud je operátor potrubí posledním tokenem na řádku, analyzátor PowerShell připojí další řádek k aktuálnímu příkazu, aby pokračoval v sestavování potrubí.
Například následující jednořádková pipelina:
Command-1 | Command-2 | Command-3
lze napsat takto:
Command-1 |
Command-2 |
Command-3
Úvodní mezery na následujících řádcích nejsou významné. Odsazení zlepšuje čitelnost.
PowerShell 7 přidává podporu pro pokračování kanálů s znakem kanálu na začátku řádku. Následující příklady ukazují, jak můžete tuto novou funkci použít.
# 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
Důležité
Při interaktivní práci v shellu vkládejte kód s rourami na začátku řádku pouze při použití Ctrl+V k vložení. Operace vložení při kliknutí pravým tlačítkem myši vkládá řádky jeden po druhém. Vzhledem k tomu, že řada nekončí znakem potrubí, PowerShell považuje vstup za dokončený a spustí tuto řadu tak, jak je zadaná.