Sdílet prostřednictvím


Informace o kanálech

Stručný popis

Kombinování příkazů do kanálů v PowerShellu

Dlouhý popis

Kanál je řada příkazů propojených operátory kanálu (|) (ASCII 124). Každý operátor kanálu 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 je možné 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ů.

Třeba

Command-1 | Command-2 | Command-3

V tomto příkladu se objekty, které Command-1 vygenerují, odešlou 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. Protože kanál neobsahuje žádné další příkazy, zobrazí se výsledky v konzole nástroje .

V kanálu se příkazy zpracovávají v pořadí zleva doprava. Zpracování se zpracovává jako jedna operace a výstup se zobrazuje při generování.

Tady je jednoduchý příklad. Následující příkaz získá proces Poznámkového bloku a pak ho zastaví.

Třeba

Get-Process notepad | Stop-Process

První příkaz použije rutinu Get-Process k získání objektu představujícího proces Poznámkového bloku. K odeslání objektu procesu do Stop-Process rutiny používá operátor kanálu (|), který zastaví proces Poznámkového bloku. Všimněte si, že Stop-Process příkaz nemá parametr Name nebo ID pro určení procesu, protože zadaný proces se odesílá prostřednictvím kanálu.

Tento příklad kanálu načte 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 každého příkazu, který se předává dalšímu příkazu v kanálu.

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 výsledky rutiny Getpředvést do jiné rutiny se stejným podstatným názvem. Výstup rutiny můžete například předvést Get-Service do Start-Service rutin nebo Stop-Service .

Tento ukázkový kanál spustí službu WMI na počítači:

Get-Service wmi | Start-Service

V dalším příkladu můžete výstup zprostředkovatele registru PowerShellu Get-Item nebo Get-ChildItem v rámci tohoto zprostředkovatele předvést do rutiny New-ItemProperty . Tento příklad přidá novou položku registru NoOfEmployees s hodnotou 8124 do klíče registru MyCompany .

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

Mnohé rutiny nástrojů, jako Get-Memberjsou , , Where-ObjectSort-Object, Group-ObjectaMeasure-Object, se používají téměř výhradně v kanálech. K těmto rutinám můžete připojit libovolný typ objektu. Tento příklad ukazuje, jak seřadit všechny procesy v počítači podle počtu otevřených popisovačů v každém procesu.

Get-Process | Sort-Object -Property handles

Objekty můžete předat do rutin formátování, exportu a výstupu, jako Format-Listjsou , 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 *

S trochou praxe zjistíte, že kombinování jednoduchých příkazů do kanálů šetří čas a zadávání a zefektivňuje skriptování.

Jak kanály fungují

Tato část vysvětluje, jak jsou vstupní objekty vázány na parametry rutiny a zpracovávány během provádění kanálu.

Přijímá vstup kanálu.

Pro podporu pipeliningu musí mít přijímající rutina parametr, který přijímá vstup kanálu. Get-Help Pomocí příkazu s možnostmi Úplný nebo Parametr určete, které parametry rutiny přijímají vstup kanálu.

Pokud například chcete zjistit, které parametry rutiny Start-Service přijímají vstup kanálu, zadejte:

Get-Help Start-Service -Full

nebo

Get-Help Start-Service -Parameter *

Nápověda pro rutinu Start-Service ukazuje, že vstup kanálu přijímají pouze parametry InputObject a Name .

-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 prostřednictvím kanálu do Start-Service, PowerShell se pokusí přidružit objekty k parametrům InputObject a Name .

Metody přijetí vstupu kanálu

Parametry rutin můžou přijímat vstup kanálu 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é je možné na tento typ převést.

    Například parametr Name přijímá Start-Service vstup kanálu podle hodnoty. 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 má vstupní objekt vlastnost se stejným názvem jako parametr.

    Parametr Name Start-Service může například přijímat objekty, které mají vlastnost Name . Pokud chcete vypsat vlastnosti objektu, předáte ho do Get-Member.

Některé parametry můžou přijímat objekty podle hodnoty nebo názvu vlastnosti, což usnadňuje přijímání vstupu z kanálu.

Vazby parametrů

Při předávání objektů z jednoho příkazu do jiného se PowerShell pokusí přidružit objekty s kanálem k parametru přijímající rutiny.

Komponenta vazby parametrů PowerShellu přidruží vstupní objekty k parametrům rutiny podle následujících kritérií:

  • Parametr musí přijímat vstup 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 se v příkazu nepoužil.

Například rutina Start-Service má mnoho parametrů, ale pouze dva z nich, Name a InputObject , přijímají vstup kanálu. Parametr Name přebírá řetězce a parametr InputObject přebírá objekty služby. Proto můžete řetězit řetězce, objekty služby a objekty s vlastnostmi, které lze převést na objekty řetězce nebo služby.

PowerShell spravuje vazby parametrů co nejefektivněji. PowerShell nemůžete navrhnout ani vynutit vytvoření vazby na konkrétní parametr. Pokud PowerShell nemůže svázat objekty s kanálem, příkaz selže.

Další informace o řešení chyb vazeb najdete v části Zkoumání chyb kanálu dále v tomto článku.

Jednorázové zpracování

Propojení objektů do příkazu se podobá 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ě je to jako použití parametru InputObject k Format-Table odeslání kolekce objektů.

Například můžeme uložit kolekci služeb do proměnné, která se předává pomocí parametru InputObject .

$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices

Nebo můžeme vložit příkaz do parametru InputObject .

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

Je tu ale důležitý rozdíl. Když do příkazu předáte více objektů, PowerShell odesílá objekty do příkazu jeden po druhém. Při použití parametru příkazu se objekty odesílají jako jeden objekt pole. Tento malý rozdíl má významné důsledky.

Při spouštění kanálu PowerShell automaticky vypisuje jakýkoli typ, který implementuje IEnumerable rozhraní, a po jednom odesílá členy kanálem. Výjimkou je [hashtable], který vyžaduje volání GetEnumerator() metody .

V následujících příkladech se pole a zatřiďovací tabulka předávají do Measure-Object rutiny, aby se spočítal počet objektů přijatých z kanálu. Pole má více členů a zatřiďovací tabulka má několik párů klíč-hodnota. Pouze pole je výčtu 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ě platí, že pokud z Get-Process rutiny do Get-Member rutiny předáte více objektů procesu, PowerShell odesílá jednotlivé objekty procesu postupně do Get-Member. Get-Member zobrazí třídu .NET (typ) procesních objektů 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 objektu Get-Member, Get-Member obdrží pole objektů System.Diagnostics.Process jako jednu jednotku. Zobrazuje vlastnosti pole objektů. (Poznamenejte si symbol pole ([]) za názvem typu System.Object .)

Třeba

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 takový, jaký jste zamýšleli. Ale až tomu porozumíte, můžete ho použít. Například všechny objekty pole mají vlastnost Count . Můžete ho použít k určení počtu procesů spuštěných v počítači.

Třeba

(Get-Process).count

Je důležité si uvědomit, že objekty odeslané kanálem se doručují po jednom.

Zkoumání chyb kanálu

Pokud PowerShell nemůže přidružit objekty s kanálem k parametru přijímající rutiny, 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á do rutiny 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 prozkoumání použijte rutinu Trace-Command ke trasování komponenty vazby parametrů PowerShellu. Následující příklad trasuje vazbu parametrů během provádění kanálu. Parametr PSHost zobrazí výsledky trasování v konzole a parametr FilePath odešle výsledky trasování do debug.txt souboru 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 zobrazují hodnoty vázané na rutinu Get-Item a pak pojmenované hodnoty, které jsou vázány na rutinu 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 s parametrem Destination selhal 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
...

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 cíl přijímá vstup kanálu pouze "podle názvu vlastnosti". Proto musí mít objekt s kanálem vlastnost s názvem Destination.

Slouží Get-Member k zobrazení vlastností objektu pocházejícího z Get-Item.

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

Výstup ukazuje, že položka je objekt Microsoft.Win32.RegistryKey , 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

Abychom tento příkaz opravili, musíme zadat cíl v rutině Move-ItemProperty a použít Get-Item k získání cesty k položce, kterou chceme přesunout.

Třeba

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

Vnitřní pokračování řádku

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 na několik řádků. Pokud je operátor potrubí posledním tokenem na řádku, parser PowerShellu připojí další řádek k aktuálnímu příkazu, aby pokračoval v sestavování kanálu.

Například následující jednořádkový kanál:

Command-1 | Command-2 | Command-3

lze napsat jako:

Command-1 |
  Command-2 |
    Command-3

Úvodní mezery na následujících řádcích nejsou významné. Odsazení zlepšuje čitelnost.

Viz také

about_PSReadLine

about_Objects

about_Parameters

about_Command_Syntax

about_ForEach