In che modo gli ambiti influenzano gli script di PowerShell
Negli script batch, le modifiche alle variabili di ambiente hanno un impatto globale sulla sessione corrente per impostazione predefinita. Per PowerShell, l'esatto opposto è vero perché gli ambiti vengono utilizzati per isolare le modifiche di uno script. Qui, esploreremo come gli ambiti influenzano gli script di PowerShell e come lavorare dentro e intorno a loro.
Cos'è un ambito?
In PowerShell, un "ambito" si riferisce all'ambiente corrente in cui è operativo uno script o una shell di comando. Gli ambiti vengono utilizzati per proteggere determinati oggetti all'interno dell'ambiente da modifiche involontarie di script o funzioni. In particolare, le seguenti cose sono protette dalle modifiche da comandi eseguiti da un altro ambito, a meno che non venga specificato diversamente dai parametri in questi comandi:
- variabili
- alias
- funzioni
- PowerShell Drives (PSDrives)
Nuovi ambiti vengono creati ogni volta che si esegue uno script o una funzione o quando si crea una nuova sessione o istanza di PowerShell. Gli ambiti creati eseguendo script e funzioni hanno una relazione "genitore / figlio" con l'ambito da cui sono stati creati. Ci sono alcuni ambiti che hanno significati particolarmente speciali e sono accessibili per nome:
- Il Globale scope è l'ambito che viene creato all'avvio di PowerShell. Include le variabili, gli alias, le funzioni e le PSDrive integrate in PowerShell e tutte le altre create dal profilo PowerShell.
- Il Locale scope si riferisce a qualunque sia lo scopo corrente. Quando avvii PowerShell farà riferimento all'ambito Globale, all'interno di uno script sarà lo scope Script, ecc.
- Il copione l'ambito viene creato quando viene eseguito uno script. Gli unici comandi che operano all'interno di questo ambito sono quelli presenti nello script.
- Privato gli ambiti possono essere definiti nell'ambito corrente, per impedire ai comandi di altri ambiti di essere in grado di leggere o modificare elementi a cui potrebbero altrimenti accedere.
Gli scope possono anche essere indicati in base al numero in alcuni comandi, in cui l'ambito corrente viene indicato come zero e i relativi antenati vengono referenziati aumentando gli interi. Ad esempio, all'interno di uno script eseguito dall'ambito Globale, l'ambito Script sarebbe 0 e l'ambito Globale sarebbe 1. Un ambito ulteriormente nidificato nell'ambito Script, ad esempio una funzione, farebbe riferimento all'ambito Globale come 2 I numeri negativi non funzioneranno per fare riferimento agli ambiti figlio - il motivo per questo sarà evidente a breve.
Come gli ambiti influenzano i comandi
Come accennato in precedenza, i comandi eseguiti all'interno di un ambito non influenzeranno le cose in un altro ambito, a meno che non sia specificamente richiesto di farlo. Ad esempio, se $ MyVar esiste nell'ambito globale e uno script esegue un comando per impostare $ MyVar su un valore diverso, la versione globale di $ MyVar rimarrà inalterata mentre una copia di $ MyVar viene inserita nello scope Script con il nuovo valore. Se un $ MyVar non esiste, uno script lo creerà all'interno dell'ambito Script per impostazione predefinita, non nell'ambito globale. Questo è importante da ricordare quando si apprende l'effettiva relazione genitore / figlio tra gli ambiti.
La relazione genitore / figlio degli ambiti in PowerShell è a senso unico. I comandi possono vedere dentro e, facoltativamente, modificare l'ambito corrente, il suo genitore e qualsiasi ambito sopra di esso. Tuttavia, non possono vedere o modificare le cose in nessun bambino nell'ambito corrente. Ciò è principalmente dovuto al fatto che, una volta spostato in un ambito genitore, l'ambito figlio è già stato distrutto perché ha raggiunto il suo scopo. Ad esempio, perché dovresti vedere o modificare una variabile nello scope Script, dall'ambito Globale, dopo che lo script è terminato? Esistono molti casi in cui è necessario che le modifiche di uno script o di una funzione persistano oltre il suo completamento, ma non così tante in cui è necessario apportare modifiche agli oggetti all'interno dello scope o dell'ambito della funzione prima o dopo l'esecuzione. (Di solito, tali cose saranno comunque gestite come parte della sceneggiatura o della funzione stessa).
Certo, quali sono le regole senza eccezioni? Un'eccezione a quanto sopra sono gli ambiti privati. Gli oggetti negli ambiti privati sono accessibili solo ai comandi eseguiti nell'ambito nell'ambito del quale sono stati creati. Un'altra importante eccezione sono gli oggetti che hanno la proprietà AllScope. Queste sono variabili speciali e alias per i quali una modifica in qualsiasi ambito influenzerà tutti gli ambiti. I seguenti comandi ti mostreranno quali variabili e alias hanno la proprietà AllScope:
Ottieni-Variabile | Where-Object $ _. Options -match 'AllScope' Get-Alias | Where-Object $ _. Options -match 'AllScope')
Ambiti in azione
Per il nostro primo sguardo sugli ambiti in azione, inizieremo in una sessione di PowerShell in cui la variabile $ MyVar è stata impostata su una stringa, 'I am a global variable!', Dalla riga di comando. Quindi, lo script seguente verrà eseguito da un file denominato Scope-Demo.ps1:
Funzione FunctionScope 'Modifica $ MyVar con una funzione.' $ MyVar = 'Sono stato impostato da una funzione!' "MyVar dice $ MyVar" "Verifica il valore corrente di $ MyVar." "MyVar dice $ MyVar" "Modifica $ MyVar per script." $ MyVar = 'Sono stato impostato da uno script!' "MyVar dice $ MyVar" "FunctionScope" Controllo del valore finale di MyVar prima dell'uscita dallo script. ' "MyVar dice $ MyVar" "
Se gli script di PowerShell funzionavano allo stesso modo degli script batch, ci aspettiamo che il valore di $ MyVar (o% MyVar% nella sintassi batch) cambi da "I am a global variable!" A "I set da uno script!" e infine a "Sono stato impostato da una funzione!" dove rimarrebbe fino a quando non verrà modificato in modo esplicito o la sessione verrà chiusa. Tuttavia, guarda cosa succede realmente qui mentre ci spostiamo attraverso ciascuno degli ambiti - in particolare, dopo che la funzione FunctionScope ha completato il suo lavoro e controlliamo nuovamente la variabile dallo Script, e successivamente dal Global, scope.
Come puoi vedere, la variabile è sembrata cambiare mentre ci muovevamo attraverso lo script perché, fino a quando la funzione FunctionScope non veniva completata, stavamo controllando la variabile dallo stesso scope che era stata modificata per l'ultima volta. Al termine di FunctionScope, siamo tornati nello scope Script in cui $ MyVar non è stato toccato dalla funzione. Poi, quando lo script è terminato, siamo tornati nello scope Globale dove non era stato affatto modificato.
Raggiungere fuori dall'ambito locale
Quindi, questo è tutto a posto per aiutarti a evitare di applicare accidentalmente modifiche all'ambiente oltre agli script e alle funzioni, ma cosa succederebbe se volessi apportare tali modifiche? Esiste una sintassi speciale e abbastanza semplice per la creazione e la modifica di oggetti oltre l'ambito locale. Basta inserire il nome dell'ambito all'inizio del nome della variabile e inserire due punti tra l'ambito e i nomi delle variabili. Come questo:
$ global: MyVar $ script: MyVar $ locale: MyVar
È possibile utilizzare questi modificatori sia durante la visualizzazione e l'impostazione delle variabili. Vediamo cosa succede con questo script dimostrativo:
Funzione FunctionScope "Modifica $ MyVar nell'ambito della funzione locale ... '$ local: MyVar =" Questo è MyVar nell'ambito locale della funzione. "' Modifica $ MyVar nell'ambito dello script ... '$ script: MyVar =' MyVar era un tempo impostato da uno script. Ora impostato da una funzione. "Modifica $ MyVar nell'ambito globale ... '$ global: MyVar =' MyVar è stato impostato nell'ambito globale. Ora impostato da una funzione. "Verifica $ MyVar in ogni ambito ..." "Locale: $ locale: MyVar" "Script: $ script: MyVar" "Globale: $ globale: MyVar" "" Ottieni il valore corrente di $ MyVar. ' "MyVar dice $ MyVar" "Modifica $ MyVar per script." $ MyVar = 'Sono stato impostato da uno script!' "MyVar dice $ MyVar" FunctionScope "Controllo di $ MyVar dall'ambito dello script prima di uscire. ' "MyVar dice $ MyVar" "
Come prima, inizieremo impostando la variabile nell'oscilloscopio Globale e terminando con il controllo del risultato dell'ambito Globale finale.
Qui puoi vedere che FunctionScope è stato in grado di cambiare la variabile nello scope Script e mantenere le modifiche dopo che è stata completata. Inoltre, la modifica della variabile nello scope Globale persisteva anche dopo che lo script era terminato. Questo può essere particolarmente utile se devi cambiare ripetutamente variabili all'interno di uno script, o nell'ambito Global, usando lo stesso codice - devi solo definire una funzione o uno script che è scritto per modificare la variabile dove e come hai bisogno di farlo, e invocatelo ogni volta che tali cambiamenti sono necessari.
Come menzionato in precedenza, i numeri degli scope possono essere usati anche in certi comandi per modificare la variabile a diversi livelli in relazione all'ambito locale. Ecco lo stesso script utilizzato nel secondo esempio sopra, ma con la funzione modificata per utilizzare i comandi Get-Variable e Set-Variable con i numeri degli ambiti anziché fare riferimento direttamente alla variabile con gli ambiti denominati:
Funzione FunctionScope "Modifica $ MyVar nell'ambito 0, relativo a FunctionScope ... 'Set-Variabile MyVar" Questo è MyVar nell'ambito della funzione 0. "-Scope 0' Modifica $ MyVar nell'ambito 1, relativo a FunctionScope ... 'Set-Variable MyVar MyVar è stato modificato nell'ambito 1, da una funzione. ' -Scope 1 'Modifica $ MyVar nell'ambito 2, relativo a Functionscope ...' Set-Variabile MyVar 'MyVar è stato modificato nell'ambito 2, da una funzione.' -Scope 2 "Controllo $ MyVar in ogni ambito ..." Ambito 0: 'Ottieni-Variabile MyVar -Scope 0 -ValueOnly' Ambito 1: 'Ottieni-Variabile MyVar -Scope 1 -ValueOnly' Ambito 2: 'Ottieni-Variabile MyVar -Scope 2 -ValueOnly "" Ottieni il valore corrente di $ MyVar. ' "MyVar dice $ MyVar" "Modifica $ MyVar per script." $ MyVar = 'Sono stato impostato da uno script!' "MyVar dice $ MyVar" FunctionScope "Controllo di $ MyVar dall'ambito dello script prima di uscire. ' "MyVar dice $ MyVar" "
Simile a prima, possiamo vedere qui come i comandi in un ambito possono modificare gli oggetti nel suo ambito genitore.
Informazioni aggiuntive
C'è ancora molto altro che può essere fatto con gli ambiti di quello che può rientrare in questo articolo. Gli ambiti influenzano più delle sole variabili e c'è ancora molto da imparare sugli ambiti privati e le variabili di AllScope. Per ulteriori informazioni utili, è possibile eseguire il seguente comando da PowerShell:
Get-Help about_scopes
Lo stesso file di aiuto è disponibile anche su TechNet.
Scope image credit: spadassin on openclipart