ARGOMENTO
about_pipelines
DESCRIZIONE BREVE
Combinazione di comandi nelle pipeline in Windows PowerShell
DESCRIZIONE DETTAGLIATA
Con il termine pipeline si definisce una serie di comandi
connessi da operatori pipeline (|) (ASCII 124). Ogni operatore
pipeline invia i risultati del comando precedente al comando
successivo.
È possibile utilizzare le pipeline per inviare gli oggetti
restituiti come output da un comando affinché vengano utilizzati
come input da un altro comando. È quindi possibile inviare
l'output di quel comando a un altro comando. Il risultato è una
catena di comandi molto potente ("pipeline") composta da una
successione di comandi semplici.
Ad esempio,
Command-1 | Command-2 | Command-3
In questo esempio gli oggetti restituiti come output da Command-1
vengono inviati a Command-2. Command-2 elabora gli oggetti e li
invia a Command-3. Command-3 elabora 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 da sinistra verso
destra nell'ordine in cui vengono visualizzati. L'elaborazione
viene gestita come una sola operazione e l'output viene
visualizzato nel modo in cui viene generato.
Di seguito è riportato un semplice esempio. Il comando seguente
ottiene il processo Notepad, quindi lo arresta.
get-process notepad | stop-process
Il primo comando utilizza il cmdlet Get-Process per ottenere un
oggetto che rappresenta il processo Notepad. Utilizza un
operatore pipeline (|) per inviare l'oggetto processo al cmdlet
Stop-Process, il quale arresta il processo Notepad. Si noti che
il comando Stop-Process non dispone di un parametro Name o ID per
specificare il processo perché il processo specificato viene
inviato attraverso la pipeline.
Di seguito è riportato un esempio pratico. Questa pipeline di
comandi ottiene i file di testo nella directory corrente,
seleziona solo i file la cui lunghezza supera i 10.000 byte, li
ordina in base alla 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 comprende quattro comandi nell'ordine
specificato. Il comando è scritto orizzontalmente, ma nel grafico
seguente il processo è illustrato verticalmente.
Get-ChildItem -path *.txt
|
| (FileInfo objects )
| ( .txt )
|
V
Where-Object {$_.length -gt 10000}
|
| (FileInfo objects )
| ( .txt )
| ( Length > 10000 )
|
V
Sort-Object -property Length
|
| (FileInfo objects )
| ( .txt )
| ( Length > 10000 )
| ( Sorted by length )
|
V
Format-Table -property name, length
|
| (FileInfo objects )
| ( .txt )
| ( Length > 10000 )
| ( Sorted by length )
| (Formatted in a table )
|
V
Name Length
---- ------
tmp1.txt 82920
tmp2.txt 114000
tmp3.txt 114000
UTILIZZO DELLE PIPELINE
I cmdlet di Windows PowerShell sono progettati per essere
utilizzati nelle pipeline. Ad esempio, è in genere possibile
reindirizzare i risultati di un cmdlet Get a un cmdlet Action
come Set, Start, Stop o Rename per lo stesso nome.
È ad esempio possibile reindirizzare qualsiasi servizio dal
cmdlet Get-Service al cmdlet Start-Service o Stop-Service
(sebbene i servizi disabilitati non possano essere riavviati in
questo modo).
Questa pipeline di comandi avvia il servizio WMI nel computer:
get-service wmi | start-service
Anche i cmdlet che ottengono e impostano oggetti dei provider di
Windows PowerShell, ad esempio i cmdlet Item e ItemProperty, sono
stati progettati per essere utilizzati nelle pipeline.
È ad esempio possibile reindirizzare i risultati di un comando
Get-Item o Get-ChildItem nel provider del Registro di sistema di
Windows PowerShell al cmdlet New-ItemProperty. Questo comando
aggiunge alla chiave del Registro di sistema MyCompany una nuova
voce, NoOfEmployees, con il valore 8124.
get-item -path HKLM:\Software\MyCompany | new-Itemproperty
-name NoOfEmployees -value 8124
Molti dei cmdlet dell'utilità, ad esempio Get-Member,
Where-Object, Sort-Object, Group-Object e Measure-Object, vengono
utilizzati quasi esclusivamente nelle pipeline. È possibile
reindirizzare qualsiasi oggetto a questi cmdlet.
È ad esempio possibile reindirizzare tutti i processi nel
computer al comando Sort-Object affinché vengano ordinati in base
al numero di handle nel processo.
get-process | sort-object -property handles
È inoltre possibile reindirizzare qualsiasi oggetto ai cmdlet di
formattazione quali Format-List e Format-Table, ai cmdlet di
esportazione quali Export-Clixml e Export-CSV e ai cmdlet di tipo
Out, ad esempio Out-Printer.
È ad esempio possibile reindirizzare il processo Winlogon al
cmdlet Format-List per visualizzare tutte le proprietà del
processo in un elenco.
get-process winlogon | format-list -property *
Con un po' di pratica, gli utenti scopriranno che combinare in
pipeline semplici comandi consente di risparmiare tempo e di
migliorare l'efficienza dell'attività di scripting.
FUNZIONAMENTO DELLE PIPELINE
Quando si "reindirizzano" oggetti, ovvero si inviano oggetti di
output di un comando a un altro comando, in Windows PowerShell
viene eseguito il tentativo di associare gli oggetti
reindirizzati a uno dei parametri del cmdlet ricevente.
A tale scopo, il componente per l'associazione dei parametri di
Windows PowerShell, che associa gli oggetti di input ai
parametri dei cmdlet, tenta di trovare un parametro che soddisfi
i criteri seguenti:
-- Il parametro deve accettare l'input da una pipeline (non
tutti lo fanno)
-- Il parametro deve accettare il tipo di oggetto inviato oppure
un tipo in cui sia possibile convertire l'oggetto.
-- Il parametro non deve essere già utilizzato nel comando.
Il cmdlet Start-Service, ad esempio, dispone di molti parametri,
ma solo due, Name e InputObject, accettano l'input da pipeline.
Il parametro Name accetta le stringhe e il parametro InputObject
accetta gli oggetti servizio. Di conseguenza, è possibile
reindirizzare a Start-Service stringhe e oggetti servizio (e
oggetti con proprietà convertibili in stringhe e in oggetti
servizio).
Se il componente per l'associazione dei parametri di Windows
PowerShell non è in grado di associare gli oggetti reindirizzati
a un parametro del cmdlet ricevente, il comando ha esito
negativo e viene richiesto di immettere i valori mancanti del
parametro.
Non è possibile forzare il componente per l'associazione dei
parametri ad associare gli oggetti reindirizzati a un
determinato parametro. Analogamente, non è possibile suggerire
un parametro. La logica del componente gestisce il
reindirizzamento nel modo più efficiente possibile.
ELABORAZIONE UNO ALLA VOLTA
Il reindirizzamento di oggetti a un comando ricorda l'utilizzo
di un parametro del comando per inviare gli oggetti.
Il reindirizzamento di oggetti che rappresentano i servizi nel
computer a un comando Format-Table, ad esempio:
get-service | format-table -property name, dependentservices
è molto simile al salvataggio degli oggetti servizio in una
variabile e all'utilizzo del parametro InputObject di
Format-Table per inviare l'oggetto servizio.
$services = get-service
format-table -inputobject $services -property name,
dependentservices
oppure all'incorporamento del comando nel valore del parametro
format-table -inputobject (get-service wmi)
-property name, dependentservices
Esiste tuttavia una differenza rilevante. Quando si
reindirizzano più oggetti a un comando, in Windows PowerShell
gli oggetti vengono inviati al comando uno alla volta. Quando si
utilizza un parametro del comando, gli oggetti vengono inviati
come un singolo oggetto matrice.
Questa differenza tecnica può avere alcune interessanti, e
talvolta utili, conseguenze.
Ad esempio, se si reindirizzano più oggetti processo dal cmdlet
Get-Process al cmdlet Get-Member, in Windows PowerShell ogni
oggetto processo viene inviato uno alla volta a Get-Member.
Get-Member visualizza la classe .NET (tipo) degli oggetti
processo e le proprietà e i metodi relativi.
(Get-Member elimina i duplicati, pertanto se gli oggetti sono
tutti dello stesso tipo, visualizza un solo tipo di oggetto.)
In questo caso, Get-Member visualizza le proprietà e i metodi di
ogni oggetto processo, ovvero di un oggetto System.Diagnostics.Pr
ocess.
get-process | get-member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize
...
Tuttavia, se si utilizza il parametro InputObject di
Get-Member, Get-Member riceve una matrice di oggetti
System.Diagnostics.Process come singola unità e visualizza le
proprietà di una matrice di oggetti. (Si noti il simbolo di
matrice ([]) dopo il nome del tipo System.Object.)
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()
...
È possibile che si ottenga un risultato non previsto, ma dopo
averlo compreso sarà comunque possibile utilizzarlo. Ad esempio,
una matrice di oggetti processo dispone di una proprietà Count
che è possibile utilizzare per contare il numero di processi nel
computer.
(get-process).count
Questa distinzione può essere importante, ricordare pertanto che
quando si reindirizzano oggetti a un cmdlet, essi vengono
recapitati uno alla volta.
ACCEPTS PIPELINE INPUT
Per poter ricevere oggetti in una pipeline, è necessario che il
cmdlet ricevente disponga di un parametro in grado di accettare
l'input da pipeline. È possibile utilizzare un comando Get-Help
con il parametro Full o Parameter per determinare quali parametri
di un cmdlet sono eventualmente in grado di accettare l'input da
pipeline.
Nella visualizzazione predefinita di Get-Help, l'elemento
"Accepts pipeline input" viene visualizzato in una tabella di
attributi di parametri. Questa tabella viene visualizzata solo
quando si utilizza il parametro Full o Parameter del cmdlet Get-Help.
Ad esempio per determinare quale dei parametri del cmdlet
Start-Service accetta l'input da pipeline, digitare:
get-help start-service -full
get-help start-service -parameter *
Ad esempio, nella Guida per il cmdlet Start-Service è indicato
che i parametri Name e InputObject accettano l'input da pipeline
("true"). Per tutti gli altri parametri è presente il valore
"false" nella riga "Accept pipeline input?"
-name <string[]>
Specifica i nomi dei servizi da avviare.
Il nome del parametro è facoltativo. È possibile
utilizzare "-Name" o il relativo alias, "-ServiceName",
oppure omettere il nome del parametro.
Required? true
Position? 1
Valore predefinito
--> Accept pipeline input? true (ByValue, ByPropertyName)
Accept wildcard characters? true
-inputObject <ServiceController[]>
Specifica gli oggetti ServiceController che rappresentano
i servizi da avviare. Immettere una variabile contenente
gli oggetti oppure digitare un comando o un'espressione
che consente di ottenere gli oggetti.
Required? false
Position? named
Valore predefinito
--> Accept pipeline input? true (ByValue)
Accept wildcard characters? false
Ciò significa che è possibile inviare oggetti (PsObjects)
attraverso la pipeline al cmdlet Where-Object e che in Windows
PowerShell l'oggetto verrà associato al parametro InputObject.
METODI DISPONIBILI PER ACCETTARE L'INPUT DA PIPELINE
I parametri dei cmdlet possono accettare l'input da pipeline in
uno di due modi diversi:
-- ByValue: i parametri che accettano l'input "in base al
valore" possono accettare gli oggetti reindirizzati aventi lo
stesso tipo .NET del valore del parametro oppure gli oggetti
convertibili in quel tipo.
Ad esempio, il parametro Name di Start-Service accetta
l'input da pipeline in base al valore. È in grado di
accettare oggetti stringa oppure oggetti convertibili in stringhe.
-- ByPropertyName: i parametri che accettano l'input "in base al
nome della proprietà" possono accettare oggetti reindirizzati
solo quando una proprietà dell'oggetto presenta lo stesso
nome del parametro.
Ad esempio, il parametro Name di Start-Service può accettare
oggetti che dispongono di una proprietà Name.
(Per elencare le proprietà di un oggetto, reindirizzarlo a
Get-Member.)
Alcuni parametri possono accettare oggetti in base al valore o
in base al nome della proprietà. Tali parametri sono stati
progettati per accettare l'input della pipeline con facilità.
ANALISI DEGLI ERRORI DELLA PIPELINE
Se un comando ha esito negativo a causa di un errore della
pipeline, è possibile analizzare l'errore e riscrivere il comando.
Ad esempio, il comando seguente tenta di spostare una voce del
Registro di sistema da una chiave a un'altra utilizzando il
cmdlet Get-Item per ottenere il percorso di destinazione e
quindi reindirizzando il percorso al cmdlet Move-ItemProperty.
In modo specifico, il comando utilizza il cmdlet Get-Item per
ottenere il percorso di destinazione. Viene utilizzato un
operatore pipeline per inviare il risultato al cmdlet
Move-ItemProperty. Il comando Move-ItemProperty 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 Windows PowerShell viene
visualizzato il messaggio di errore seguente:
Move-ItemProperty: Impossibile associare l'oggetto di input
a qualsiasi parametro del comando. Il comando non accetta
l'input da pipeline oppure l'input e le relative proprietà
non corrispondono ad alcun parametro che accetta l'input da
pipeline.
At line:1 char:23
+ $a | move-itemproperty <<<< -path hklm:\software\mycompany\
design -name product
Per analizzare l'errore, utilizzare il cmdlet Trace-Command per
analizzare il componente per l'associazione dei parametri di
Windows PowerShell. Il comando seguente analizza il componente
per l'associazione dei parametri durante l'elaborazione. Vengono
utilizzati il parametro -pshost per visualizzare i risultati
nella console e il comando -filepath per inviarli al file
debug.txt per riferimenti futuri.
trace-command -name parameterbinding -expression {get-item -path
hklm:\software\mycompany\sales | move-itemproperty -path
hklm:\software\mycompany\design -name product} -pshost -filepath debug.txt
I risultati dell'analisi sono lunghi, ma mostrano i valori
associati al cmdlet Get-Item e i valori denominati associati al
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]
...
Infine, mostrano che il tentativo di associare il percorso al
parametro Destination di Move-ItemProperty ha avuto esito negativo.
...
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 ...
Per analizzare l'errore, utilizzare il cmdlet Get-Help per
visualizzare gli attributi del parametro Destination. Mediante
il comando seguente è possibile ottenere informazioni
dettagliate sul parametro Destination.
get-help move-itemproperty -parameter destination
I risultati mostrano che il parametro Destination accetta
l'input da pipeline solo "in base al nome della proprietà".
Ciò significa che l'oggetto reindirizzato deve disporre di una
proprietà denominata Destination.
-destination <string>
Specifica il percorso di destinazione.
Required? true
Position? 2
Valore predefinito
Accept pipeline input? true (ByPropertyName)
Accept wildcard characters? true
Per visualizzare le proprietà dell'oggetto reindirizzato al
cmdlet Move-ItemProperty, reindirizzarlo al cmdlet Get-Member.
Il comando seguente reindirizza i risultati della prima parte
del comando al cmdlet Get-Member.
get-item -path hklm:\software\mycompany\sales | get-member
L'output indica che si tratta di un elemento Microsoft.Win32.Regi
stryKey che non dispone di una proprietà Destination. Questo
spiega perché il comando ha avuto esito negativo.
Per correggere il comando, è necessario specificare la
destinazione nel cmdlet Move-ItemProperty. È possibile
utilizzare un comando Get-ItemProperty per ottenere il percorso,
ma il nome e la destinazione devono essere specificati nella
parte Move-ItemProperty del comando.
get-item -path hklm:\software\mycompany\design |
move-itemproperty -dest hklm:\software\mycompany\design
-name product
Per accertare il corretto funzionamento del comando, utilizzare
un comando Get-ItemProperty:
get-itemproperty hklm:\software\mycompany\sales
I risultati mostrano che la voce del Registro di sistema Product
è stata spostata alla chiave Sales.
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\software\mycomp any\sales
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\software\mycomp any
PSChildName : sales
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
Product : 18
VEDERE ANCHE
about_objects
about_parameters
about_command_syntax
about_foreach