Condividi tramite


Informazioni sulle pipeline

Breve descrizione

Combinare i comandi in pipeline in PowerShell

Descrizione lunga

Una pipeline è una serie di comandi connessi da operatori pipeline ( | ) (ASCII 124). Ogni operatore pipeline invia i risultati del comando precedente al comando successivo.

L'output del primo comando può essere inviato per l'elaborazione come input per il secondo comando. E questo output può essere inviato a un altro comando. Il risultato è una catena di comandi complessa o una pipeline costituita da una serie di semplici comandi.

Ad esempio,

Command-1 | Command-2 | Command-3

In questo esempio, gli oggetti Command-1 generati da vengono inviati a Command-2 . Command-2elabora gli oggetti e li invia a Command-3 . Command-3elabora gli oggetti e li invia alla pipeline. Poiché nella pipeline non sono presenti altri comandi, i risultati vengono visualizzati nella console.

In una pipeline, i comandi vengono elaborati in ordine da sinistra a destra. L'elaborazione viene gestita come una singola operazione e l'output viene visualizzato quando viene generato.

Ecco un semplice esempio. Il comando seguente ottiene il processo del blocco note e quindi lo arresta.

Ad esempio,

Get-Process notepad | Stop-Process

Il primo comando usa il Get-Process cmdlet per ottenere un oggetto che rappresenta il processo del blocco note. Usa un operatore pipeline ( | ) per inviare l'oggetto processo al Stop-Process cmdlet, che interrompe il processo del blocco note. Si noti che il Stop-Process comando non ha un nome o un parametro ID per specificare il processo, perché il processo specificato viene inviato tramite la pipeline.

Questa pipeline di esempio ottiene i file di testo nella directory corrente, seleziona solo i file con una lunghezza superiore a 10.000 byte, li ordina per lunghezza e visualizza il nome e la lunghezza di ogni file in una tabella.

Get-ChildItem -Path *.txt |
  Where-Object {$_.length -gt 10000} |
    Sort-Object -Property length |
      Format-Table -Property name, length

Questa pipeline è costituita da quattro comandi nell'ordine specificato. La figura seguente mostra l'output di ogni comando che viene passato al comando successivo nella pipeline.

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

Uso di pipeline

La maggior parte dei cmdlet di PowerShell è progettata per supportare le pipeline. Nella maggior parte dei casi, è possibile inviare tramite pipe i risultati di un cmdlet Get a un altro cmdlet dello stesso sostantivo. Ad esempio, è possibile inviare tramite pipe l'output del Get-Service cmdlet ai Start-Service Stop-Service cmdlet o.

Questa pipeline di esempio avvia il servizio WMI nel computer:

Get-Service wmi | Start-Service

Per un altro esempio, è possibile inviare tramite pipe l'output di Get-Item o Get-ChildItem all'interno del provider del registro di sistema di PowerShell al New-ItemProperty cmdlet. In questo esempio viene aggiunta una nuova voce del registro di sistema, NoOfEmployees, con valore 8124, alla chiave del registro di sistema MyCompany .

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

Molti cmdlet di utilità, ad esempio,, Get-Member Where-Object Sort-Object , Group-Object e Measure-Object vengono utilizzati quasi esclusivamente nelle pipeline. È possibile inviare tramite pipe qualsiasi tipo di oggetto a questi cmdlet. Questo esempio illustra come ordinare tutti i processi nel computer in base al numero di handle aperti in ogni processo.

Get-Process | Sort-Object -Property handles

È possibile inviare oggetti tramite pipe ai cmdlet di formattazione, esportazione e output, ad esempio Format-List , Format-Table , Export-Clixml , Export-CSV e Out-File .

Questo esempio illustra come usare il Format-List cmdlet per visualizzare un elenco di proprietà per un oggetto processo.

Get-Process winlogon | Format-List -Property *

Con un po' di pratica, si noterà che la combinazione di semplici comandi in pipeline consente di risparmiare tempo e digitando e rende più efficiente lo scripting.

Funzionamento delle pipeline

Questa sezione illustra il modo in cui gli oggetti di input vengono associati ai parametri dei cmdlet ed elaborati durante l'esecuzione della pipeline.

Accetta input pipeline

Per supportare il pipelining, il cmdlet di ricezione deve avere un parametro che accetti l'input della pipeline. Usare il Get-Help comando con le opzioni complete o del parametro per determinare quali parametri di un cmdlet accettano input della pipeline.

Ad esempio, per determinare quale dei parametri del Start-Service cmdlet accetta input della pipeline, digitare:

Get-Help Start-Service -Full

oppure

Get-Help Start-Service -Parameter *

La guida per il Start-Service cmdlet indica che solo i parametri InputObject e Name accettano l'input della pipeline.

-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

Quando si inviano oggetti tramite la pipeline a Start-Service , PowerShell tenta di associare gli oggetti con i parametri InputObject e Name .

Metodi di accettazione dell'input della pipeline

I parametri dei cmdlet possono accettare input della pipeline in uno dei due modi seguenti:

  • ByValue: il parametro accetta valori che corrispondono al tipo .NET previsto o che possono essere convertiti in tale tipo.

    Ad esempio, il parametro Name di Start-Service accetta input della pipeline per valore. Può accettare oggetti stringa o oggetti che possono essere convertiti in stringhe.

  • ByPropertyName: il parametro accetta input solo quando l'oggetto di input ha una proprietà con lo stesso nome del parametro.

    Ad esempio, il parametro Name di Start-Service può accettare oggetti con una proprietà Name . Per elencare le proprietà di un oggetto, inviarlo tramite pipe a Get-Member .

Alcuni parametri possono accettare oggetti in base al nome del valore o della proprietà, semplificando l'input dalla pipeline.

Associazione di parametri

Quando si inviano tramite pipe oggetti da un comando a un altro comando, PowerShell tenta di associare gli oggetti inviati tramite pipe a un parametro del cmdlet di destinazione.

Il componente di associazione dei parametri di PowerShell associa gli oggetti di input ai parametri dei cmdlet in base ai criteri seguenti:

  • Il parametro deve accettare l'input da una pipeline.
  • Il parametro deve accettare il tipo di oggetto inviato o un tipo che può essere convertito nel tipo previsto.
  • Il parametro non è stato usato nel comando.

Ad esempio, il Start-Service cmdlet ha molti parametri, ma solo due di essi, Name e InputObject accettano input della pipeline. Il parametro Name accetta le stringhe e il parametro InputObject accetta oggetti servizio. Pertanto, è possibile inviare tramite pipe stringhe, oggetti servizio e oggetti con proprietà che possono essere convertite in oggetti stringa o servizio.

PowerShell gestisce l'associazione di parametri nel modo più efficiente possibile. Non è possibile suggerire o forzare l'associazione di PowerShell a un parametro specifico. Il comando non riesce se PowerShell non è in grado di associare gli oggetti inviati tramite pipe.

Per ulteriori informazioni sulla risoluzione dei problemi relativi agli errori di binding, vedere analisi degli errori della pipeline più avanti in questo articolo.

Elaborazione uno alla volta

Il piping di oggetti a un comando è molto simile all'uso di un parametro del comando per inviare gli oggetti. Viene ora esaminato un esempio di pipeline. In questo esempio viene usata una pipeline per visualizzare una tabella di oggetti servizio.

Get-Service | Format-Table -Property Name, DependentServices

Dal punto di vista funzionale, questo è come usare il parametro InputObject di Format-Table per inviare la raccolta di oggetti.

Ad esempio, è possibile salvare la raccolta di servizi in una variabile che viene passata usando il parametro InputObject .

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

In alternativa, è possibile incorporare il comando nel parametro InputObject .

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

Tuttavia, esiste una differenza importante. Quando si inviano tramite pipe più oggetti a un comando, PowerShell invia gli oggetti al comando uno alla volta. Quando si usa un parametro del comando, gli oggetti vengono inviati come singolo oggetto matrice. Questa differenza minore ha conseguenze significative.

Quando si esegue una pipeline, PowerShell enumera automaticamente qualsiasi tipo che implementa l' IEnumerable interfaccia e invia i membri tramite la pipeline uno alla volta. L'eccezione è [hashtable] , che richiede una chiamata al GetEnumerator() metodo.

Negli esempi seguenti, una matrice e una tabella hash vengono reindirizzate al Measure-Object cmdlet per conteggiare il numero di oggetti ricevuti dalla pipeline. La matrice dispone di più membri e la tabella hash contiene più coppie chiave-valore. Solo la matrice viene enumerata una alla volta.

@(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 :

Analogamente, se si inviano tramite pipe più oggetti processo dal Get-Process cmdlet al Get-Member cmdlet, PowerShell invia ogni oggetto processo, uno alla volta, a Get-Member . Get-MemberVisualizza la classe .NET (tipo) degli oggetti processo e i relativi metodi e proprietà.

Get-Process | Get-Member
TypeName: System.Diagnostics.Process

Name      MemberType     Definition
----      ----------     ----------
Handles   AliasProperty  Handles = Handlecount
Name      AliasProperty  Name = ProcessName
NPM       AliasProperty  NPM = NonpagedSystemMemorySize
...

Nota

Get-MemberElimina i duplicati, pertanto se gli oggetti sono dello stesso tipo, viene visualizzato solo un tipo di oggetto.

Tuttavia, se si usa il parametro InputObject di Get-Member , Get-Member riceve una matrice di oggetti System. Diagnostics. Process come una singola unità. Vengono visualizzate le proprietà di una matrice di oggetti. (Si noti il simbolo di matrice ( [] ) dopo il nome del tipo System. Object .)

Ad esempio,

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()
...

Questo risultato potrebbe non essere quello previsto. Tuttavia, dopo averla interpretata, è possibile usarla. Ad esempio, tutti gli oggetti Array hanno una proprietà count . È possibile usarlo per conteggiare il numero di processi in esecuzione nel computer.

Ad esempio,

(Get-Process).count

È importante ricordare che gli oggetti inviati alla pipeline vengono recapitati uno alla volta.

Analisi degli errori della pipeline

Quando PowerShell non è in grado di associare gli oggetti inviati tramite pipe a un parametro del cmdlet di destinazione, il comando ha esito negativo.

Nell'esempio seguente si tenta di spostare una voce del registro di sistema da una chiave del registro di sistema a un'altra. Il Get-Item cmdlet ottiene il percorso di destinazione, che viene quindi inviato tramite pipe al Move-ItemProperty cmdlet. Il Move-ItemProperty comando specifica il percorso corrente e il nome della voce del registro di sistema da spostare.

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

Il comando ha esito negativo e in PowerShell viene visualizzato il messaggio di errore seguente:

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

Per esaminare, usare il Trace-Command cmdlet per tracciare il componente di associazione dei parametri di PowerShell. Nell'esempio seguente viene tracciata l'associazione di parametri durante l'esecuzione della pipeline. Il parametro PSHost Visualizza i risultati della traccia nella console e il parametro filePath invia i risultati della traccia al debug.txt file per farvi riferimento in un secondo momento.

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
}

I risultati della traccia sono lunghi, ma visualizzano i valori associati al Get-Item cmdlet, quindi i valori denominati vengono associati al 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`]
...

Infine, viene mostrato che il tentativo di associare il percorso al parametro di destinazione di Move-ItemProperty non è riuscito.

...
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
...

Usare il Get-Help cmdlet per visualizzare gli attributi del parametro di destinazione .

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

I risultati mostrano che la destinazione accetta solo l'input della pipeline "per nome proprietà". Pertanto, l'oggetto inviato tramite pipe deve disporre di una proprietà denominata Destination.

Usare Get-Member per visualizzare le proprietà dell'oggetto proveniente da Get-Item .

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

L'output mostra che l'elemento è un oggetto Microsoft. Win32. RegistryKey che non dispone di una proprietà di destinazione . Viene illustrato il motivo per cui il comando non è riuscito.

Il parametro path accetta input della pipeline in base al nome o al valore.

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

Per correggere il comando, è necessario specificare la destinazione nel Move-ItemProperty cmdlet e utilizzare Get-Item per ottenere il percorso dell'elemento che si desidera spostare.

Ad esempio,

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

Continuazione di riga intrinseca

Come già illustrato, una pipeline è una serie di comandi connessi da operatori pipeline ( | ), in genere scritti su una sola riga. Tuttavia, per migliorare la leggibilità, PowerShell consente di suddividere la pipeline in più righe. Quando un operatore pipe è l'ultimo token sulla riga, il parser di PowerShell unisce la riga successiva al comando corrente per continuare la costruzione della pipeline.

Ad esempio, la pipeline a riga singola seguente:

Command-1 | Command-2 | Command-3

può essere scritto come:

Command-1 |
  Command-2 |
    Command-3

Gli spazi iniziali sulle righe successive non sono significativi. Il rientro migliora la leggibilità.

Vedere anche

about_PSReadLine

about_Objects

about_Parameters

about_Command_Syntax

about_ForEach