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