Windows PowerShell

Che cosa l'archivia is $ _?

Don Jones

W uando sto eseguendo una lezione della classe o una conferenza di Windows PowerShell, mi piace trot all'esterno di una riga simile al seguente:

Importazione CSV c:\users.csv | foreach-Object {New QADUser - logonname $ _.username - nome $ _.Name}

In effetti, in una recente conferenza TechMentor, ho iniziato mia sessioni con qualcosa di simile e ho utilizzato una versione più lungo in parlare a Tech-ed. Questa riga consente di importare un elenco di informazioni utente da un file con estensione csv e quindi attiva tali informazioni in nuovi utenti in Active Directory. È un'ottima demo perché dimostra che Windows PowerShell può essere eseguita piuttosto molto semplicemente in esecuzione comandi anziché dover programma lingue con alfabeti complessi.

Ma molto tempo dopo ho spostata in altri dimostrazioni, è presente una cosa che effettua ancora occhi persone incrociati: $_. Nelle esercitazioni pratiche classi, vedrà studenti tentando di riprodurre con $ _on riga di comando, senza quantità fortuna. Forum di discussione in linea, vedrà persone porre domande sull'oggetto stesso, cercando di comprendere il significato. Fortunatamente, la risposta è semplice, se non è esattamente semplice.

Passando la contrastare in corso... RO, oggetto

Tenere presente che tutti i dati in Windows PowerShell è un oggetto. È in genere possibile ignorare tali fatti, sono bello poiché gli oggetti sono tra i problemi di sviluppatore di software possono rendere facilmente per una discussione confusione. Verranno tentare evitare gli aspetti più confusione con questo semplice esempio:

Get Service

Questo cmdlet produce una serie di oggetti del servizio. Ciò significa semplicemente che possibile inviare ad altri cmdlet accettare gli oggetti del servizio come input:

Servizio Get | Interrompi servizio

Ma non vengono effettivamente eseguiti che, a meno che non si è interessati l'arresto di ogni servizio nel computer--che verrà probabilmente si arresti in maniera anomala, se non arrestarlo in modo imprevisto. In sostanza, Stop Service può accettare gli oggetti del servizio, tra le altre cose, come input, che informa i servizi da interrompere. Alcuni cmdlet sono più ampiamente accettando e può richiedere praticamente qualsiasi tipo di oggetto come input:

Servizio Get | oggetto Ordina Name
Get-processo | nome Ordina oggetto

In questi esempi, Ordina Object è perfettamente felice di lavorare con uno dei due oggetti del servizio o elaborare gli oggetti, inserendoli nell'ordine da qualunque oggetto proprietà--in entrambi i casi, la proprietà Name--specificato dall'utente.

Tecnicamente parlando Name è accettate tramite il cmdlet - proprietà parametro, ovvero che potesse avere scritto una riga di comando più completa, ad esempio:

Process Get | oggetto Ordina-proprietà Name

Ciò significa che, "Take questi oggetti e li Ordina sulla proprietà Name". 
Ogni cmdlet ha uno o più parametri che consentono di personalizzare il comportamento del cmdlet in modo alcuni. Oggetto di ordinamento, ad esempio, ha un altro parametro che consente di invertire l'ordine dell'ordinamento:

Process Get | oggetto Ordina - proprietà Name - decrescente

A prescindere dal fatto che, Ordina oggetti richiede gli oggetti di input, inserendoli in un ordine diverso e l'output di tali oggetti nella loro nuova sequenza stesse.

Super parametri: Scriptblocks

Alcuni cmdlet particolarmente potenti può avere intero script assegnato come parametri. Windows PowerShell in genere riferito a questi come scriptblocks, perché--Beh, poiché ciascuno di essi è un blocco di codice di script. Più frequentemente sono costituiti da un blocco di comandi anziché uno script che implicano programmazione dettagliata, ma è possibile inserire praticamente qualsiasi elemento in un scriptblock.

Uno di questi cmdlet è WHERE-Object. Accetta come input una serie di oggetti--non eseguirà qualsiasi tipo di oggetto--e quindi viene eseguito un scriptblock una volta per ciascun oggetto era di input.

Se tale scriptblock restituisce il valore booleano true, l'oggetto in reindirizzato viene reindirizzato; se il scriptblock restituisce false, l'oggetto in reindirizzato viene scartato. In questo modo è possibile utilizzare Where-Object per filtro oggetti basati su alcuni criteri. come nell'esempio seguente:

WmiObject Get-classe Win32_Service | Where-Object-filterscript {$ _.State - eq "Running"}

È presente tale $ _ nuovamente. In realtà, sia l'opzione-classe e - filterscript parametri sono posizionali, vale a dire che, purché si passa un valore nella prima posizione, non è necessario il nome del parametro effettivo. Ciò significa che in genere si vedrà un esempio di questo scritto come:

Get WmiObject Win32_Service | Where-Object {$ _.State - eq "Running"}

Ma è la stessa cosa. Le parentesi graffe sono che la shell del standardizzati modo di un scriptblock di inclusione. In questo caso, il scriptblock è molto di uno script affatto; è un confronto piuttosto semplice. E che è in cui $ _ è disponibile in: È importante ricordare che il scriptblock verrà eseguito una sola volta per ogni oggetto reindirizzato in. Quando viene eseguito il scriptblock, $ _ viene sostituito con l'oggetto di input corrente. In altre parole, $ _ è un segnaposto per l'oggetto pipeline corrente. $ _ è possibile confrontare le proprietà dell'oggetto--ad esempio la proprietà state--con i valori, ad esempio "Running".

Che cos'è in un nome?

Ho sempre ho pensato che $ _ è stato un pezzo dispari della sintassi. In diversi momenti, ho ho pensato che reindirizzato aggiuntivo di un nome più facile lettura, ad esempio $ o $ inputobject potrebbe essere più comprensibili, ma $ _ è almeno facile da digitare. Mi dicono $ _ stato ottenuto il nome perché il carattere di sottolineatura è simile a un carattere di pipeline (|) posizione laterale, implicando che contiene qualsiasi altro elemento è stato reindirizzato.

La persona che ha comunicato mi ciò è stato in una posizione conoscere ad ed era abbastanza grave--ma mio marcia ritiene comunque leggermente tugged-su. Ho deciso che, per quanto mi riguarda, $ _ rappresenta una casella vuota, come in "compilare il campo vuoto." È un campo vuoto ottiene compilato automaticamente tramite la shell quando viene eseguito il scriptblock.

E questo ambito si trova la chiave Ottiene la maggior parte delle persone confuso: $ _ è solo valido e utilizzabile in posizioni specifiche in cui Windows PowerShell in modo esplicito è alla ricerca di esso e preparati per sostituire con alcuni oggetti di input. Un'unica posizione di questo tipo è scriptblock utilizzato per i cmdlet Where-Object e foreach-Object (ad esempio quello all'inizio di questo articolo).

Un'altra posizione è all'interno del blocco PROCESS di determinati tipi di funzioni Windows PowerShell. Ma, naturalmente, non è semplicemente possibile digitare $ _.Status sulla riga di comando della shell e previsto per poterlo utilizzare. La shell non è cercando $ _ a quel punto, in modo non viene sostituito con qualsiasi elemento $ _; è essenzialmente un valore non definito.

Nidifica: Non Just per cani

Un'altra situazione di confusione può verificarsi quando avete scriptblocks nidificati. Si prenda in considerazione in questo esempio, che legge un elenco di nomi di computer da un file (un nome per riga) e tenta di riavviarle tutti utilizzando Strumentazione gestione Windows (WMI):

Contenuto Get c:\names.txt | foreach-Object {Get-WmiObject - nomecomputer $ _ - classe Win32_OperatingSystem | foreach-Object {$_.Reboot()}}

Ciò può ottenere un po' più semplice da leggere se si interrompe questo verrà considerato come un'unica riga di comando e invece applicare un formato di facile integrazione umane:

Contenuto Get c:\names.txt | foreach-Object {Get-WmiObject - nomecomputer $ _ - classe Win32_OperatingSystem | foreach-Object {$_.Reboot()}}

 

In questo caso, è più facile capire che non vi siano nidificati cmdlet foreach-Object. Ognuno ha un scriptblock e ogni scriptblock utilizza $ _. Il trucco è che nel corso di questa riga di comando $ _ cambi effettivamente relativo significato, ma sempre contiene uno degli oggetti che è stato reindirizzato a quel cmdlet foreach-Object.

Pertanto, prima foreach-Object riceva i nomi dei computer da Get-Content; pertanto, prima $ _ contiene i nomi dei computer sono venga assegnati al parametro - computername.

Foreach-Object secondo è ricezione dell'input da Get-WmiObject, in modo relativo $ _ contenga tali oggetti WMI--in particolare, le istanze della classe Win32_OperatingSystem che dispongono di un metodo pratico di Reboot().

Di seguito è un trucco per scoprire quale $ _ contiene: È importante ricordare che essa conterrà sempre oggetti prodotti dal cmdlet successivo a sinistra della riga di comando.

Quando si ottengono situazioni molto nidificate come questo, in grado di traccia con le versioni precedenti consentono di scoprire cosa sta succedendo più facilmente.

È sempre i problemi correlati all'

Ho sempre ho ritenuto che la differenza tra il computer in un newbie di Windows PowerShell e un guru non studiare tutti i comandi disponibili o in grado di scrivere script complessi. Invece, è in grado di master di alcuni "aspetti negativi" o dispari parti di sintassi, in ogni shell o linguaggio fornito con. $ _ è uno di quelli. È difficile capire semplicemente osservando esso viene quale $ _.

Ma ora che conosci, è possibile iniziare a utilizzare in più comandi personalizzati. Come procedere, verrà master esso--e spostare che molto più vicino alla fase un

Guru di Windows PowerShell.

 

Don Jones è uno degli istruttori Windows PowerShell più esperti del paese e i processi di scrittura. Suggerimenti settimanale Windows PowerShell ha blog all'indirizzo ConcentratedTech.com; inoltre contattarlo o domande lui di vi .