Skip to main content

Come gli ambiti influenzano gli script di PowerShell

Come gli ambiti influenzano gli script di PowerShell

Geoffrey Carr

Negli script batch, le modifiche alle variabili di ambiente hanno un impatto globale sulla sessione corrente per impostazione predefinita. Per PowerShell, l'esatto contrario è 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 che i comandi di altri ambiti possano leggere o modificare gli 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, come 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 impara a conoscere la reale relazione genitore / figlio tra gli ambiti.

La relazione genitore / figlio degli ambiti in PowerShell è a senso unico. I comandi possono vedere in, e facoltativamente modificare, l'ambito corrente, il suo genitore e qualsiasi ambito sopra quello. 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 nell'ambito 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 dell'ambito dello script o della funzione prima o dopo l'esecuzione. (Di solito, tali cose saranno gestite comunque 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:

Get-Variable | 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:

Function FunctionScope { 'Changing $MyVar with a function.' $MyVar = 'I got set by a function!' 'MyVar says $MyVar' } '' 'Checking current value of $MyVar.' 'MyVar says $MyVar' '' 'Changing $MyVar by script.' $MyVar = 'I got set by a script!' 'MyVar says $MyVar' '' FunctionScope '' 'Checking final value of MyVar before script exit.' 'MyVar says $MyVar' ''

Se gli script di PowerShell funzionavano allo stesso modo degli script batch, ci aspettiamo che il valore di $ MyVar (o% MyVar% in 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à terminata. 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 stato modificato 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 è stato modificato affatto.

Raggiungere fuori dall'ambito locale

Quindi, tutto questo è utile per evitare di applicare accidentalmente modifiche all'ambiente oltre agli script e alle funzioni, ma cosa succede se si desidera apportare tali modifiche? C'è una sintassi speciale e abbastanza semplice per creare e modificare 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 $local:MyVar

È possibile utilizzare questi modificatori sia durante la visualizzazione e l'impostazione delle variabili. Vediamo cosa succede con questo script dimostrativo:

Function FunctionScope { '' 'Changing $MyVar in the local function scope...' $local:MyVar = 'This is MyVar in the function's local scope.' 'Changing $MyVar in the script scope...' $script:MyVar = 'MyVar used to be set by a script. Now set by a function.' 'Changing $MyVar in the global scope...' $global:MyVar = 'MyVar was set in the global scope. Now set by a function.' '' 'Checking $MyVar in each scope...' 'Local: $local:MyVar' 'Script: $script:MyVar' 'Global: $global:MyVar' '' } '' 'Getting current value of $MyVar.' 'MyVar says $MyVar' '' 'Changing $MyVar by script.' $MyVar = 'I got set by a script!' 'MyVar says $MyVar' FunctionScope 'Checking $MyVar from script scope before exit.' 'MyVar says $MyVar' ''

Come prima, inizieremo impostando la variabile nello scope 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 di Global, usando lo stesso codice, 'definisci semplicemente una funzione o uno script che è stato scritto per modificare la variabile dove e come ne hai bisogno fatto, 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 usato nel secondo esempio sopra, ma con la funzione modificata per usare i comandi Get-Variable e Set-Variable con i numeri degli scope invece di fare riferimento direttamente alla variabile con gli scope nominati:

Function FunctionScope { '' 'Changing $MyVar in scope 0, relative to FunctionScope...' Set-Variable MyVar 'This is MyVar in the function's scope 0.' –Scope 0 'Changing $MyVar in scope 1, relative to FunctionScope...' Set-Variable MyVar 'MyVar was changed in scope 1, from a function.' –Scope 1 'Changing $MyVar in scope 2, relative to Functionscope...' Set-Variable MyVar 'MyVar was changed in scope 2, from a function.' –Scope 2 '' 'Checking $MyVar in each scope...' ‘Scope 0:’ Get-Variable MyVar –Scope 0 –ValueOnly ‘Scope 1:’ Get-Variable MyVar –Scope 1 –ValueOnly ‘Scope 2:’ Get-Variable MyVar –Scope 2 –ValueOnly '' } '' 'Getting current value of $MyVar.' 'MyVar says $MyVar' '' 'Changing $MyVar by script.' $MyVar = 'I got set by a script!' 'MyVar says $MyVar' FunctionScope 'Checking $MyVar from script scope before exit.' 'MyVar says $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 di più 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

Link
Plus
Send
Send
Pin