En los scripts por lotes, los cambios en las variables de entorno tienen un impacto global en la sesión actual de forma predeterminada. Para PowerShell, es exactamente lo contrario porque los ámbitos se utilizan para aislar cambios en un script. Aquí, exploraremos cómo afectan los ámbitos a los scripts de PowerShell y cómo trabajar en ellos y alrededor de ellos.
¿Qué es un alcance?
En PowerShell, un «alcance» se refiere al entorno actual en el que opera un script o shell de comandos. Los ámbitos se utilizan para proteger ciertos objetos en el entorno contra modificaciones involuntarias por parte de scripts o funciones. En particular, lo siguiente está protegido contra modificaciones por comandos ejecutados desde otro ámbito, a menos que los parámetros de esos comandos especifiquen lo contrario:
- Variables
- También conocido como
- Las funciones
- Unidades PowerShell (PSDrives)
Se crean nuevos ámbitos cada vez que ejecuta una secuencia de comandos o una función, o cuando crea una nueva sesión o instancia de PowerShell. Los ámbitos creados mediante la ejecución de scripts y funciones tienen una relación «principal / secundario» con el ámbito desde el que se crearon. Hay algunos pentagramas que tienen significados particularmente especiales y se puede acceder a ellos por su nombre:
- los Global alcance es el alcance que se crea cuando se inicia PowerShell. Incluye las variables, alias, funciones y PSDrives integrados en PowerShell, así como los creados por su perfil de PowerShell.
- los Local Alcance se refiere al alcance actual. Cuando inicie PowerShell, se referirá al alcance global, en un script este será el alcance del script, etc.
- los Guión el alcance se crea cuando se ejecuta un script. Los únicos comandos que funcionan en este ámbito son los que están en el script.
- Privado Los ámbitos se pueden definir en el ámbito actual para evitar que los comandos de otros pentagramas lean o modifiquen elementos a los que de otro modo podrían tener acceso.
También se puede hacer referencia a los pentagramas por número en algunos comandos, donde el pentagrama actual se denota con cero y sus antepasados se referencian mediante números enteros crecientes. Por ejemplo, en un script ejecutado desde un alcance global, el alcance del Script sería 0 y el alcance global sería 1. Un alcance que estuviera más anidado dentro del alcance del Script, como una función, se referiría al alcance global como 2 Sin embargo , los números negativos no funcionarán para hacer referencia a ámbitos secundarios; la razón será evidente en breve.
Cómo afectan los ámbitos a los comandos
Como se mencionó anteriormente, los comandos ejecutados en un alcance no afectarán las cosas en otro alcance, a menos que se le indique específicamente que lo haga. Por ejemplo, si $ MyVar existe en el alcance global y una secuencia de comandos ejecuta un comando para establecer $ MyVar en un valor diferente, la versión global de $ MyVar permanecerá sin cambios mientras se coloca una copia de $ MyVar en el alcance de la secuencia de comandos. Con el nuevo valor . Si $ MyVar no existe, una secuencia de comandos la creará en el alcance de la secuencia de comandos predeterminada, no en el alcance global. Es importante recordar esto cuando descubra la relación padre / hijo real entre los ámbitos.
La relación padre / hijo de los ámbitos en PowerShell es unidireccional. Los controles pueden ver y, opcionalmente, modificar el pentagrama actual, su padre y cualquier pentagrama superior. Sin embargo, no pueden ver ni editar elementos en los elementos secundarios del ámbito actual. Esto se debe principalmente a que, una vez que cambia a un ámbito principal, el ámbito secundario ya se ha destruido porque cumplió su propósito. Por ejemplo, ¿por qué debería ver o modificar una variable en el alcance del script, desde el alcance global, una vez finalizado el script? Hay muchos casos en los que necesita cambios en un script o función para persistir más allá de su finalización, pero no tantos en los que necesitaría realizar cambios en objetos dentro del alcance del script o función. La función antes o después de su ejecución. (Por lo general, estas cosas se manejarán como parte del script o de la función en sí de todos modos).
Por supuesto, ¿cuáles son las reglas sin excepciones? Una excepción a lo anterior son los ámbitos privados. Los objetos en ámbitos privados solo son accesibles para los comandos ejecutados en el ámbito desde el que se crearon. Otra excepción importante son los elementos que tienen la propiedad AllScope. Se trata de variables y alias especiales para los que un cambio de cualquier ámbito afectará a todos los ámbitos. Los siguientes comandos le mostrarán qué variables y alias tienen la propiedad AllScope:
Get-Variable | Where-Object {$_.Options -match 'AllScope'} Get-Alias | Where-Object {$_.Options -match 'AllScope')
Visores en acción
Para nuestro primer vistazo a los ámbitos en acción, comenzaremos en una sesión de PowerShell donde la variable $ MyVar se ha establecido en una cadena, «¡Soy una variable global!» », Desde la línea de comando. Luego, el siguiente script se ejecutará desde un archivo llamado 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" ''
Si los scripts de PowerShell funcionaran igual que los scripts por lotes, esperaríamos que el valor de $ MyVar (o% MyVar% en la sintaxis del lote) cambie de «¡Soy una variable global!» ¡»A» me definió un guión! «, Y finalmente a» ¡Me arreglé por una función! Dónde permanecería hasta que se cambiara explícitamente de nuevo o se terminara la sesión. Sin embargo, vea lo que realmente sucede aquí a medida que avanzamos por cada uno de los alcances, específicamente, después de que la función FunctionScope termina su trabajo y verificamos la variable nuevamente desde Script y luego desde el alcance global.
Comme vous pouvez le voir, la variable semblait changer au fur et à mesure que nous parcourions le script car, jusqu’à ce que la fonction FunctionScope soit terminée, nous vérifiions la variable à partir de la même portée qu’elle a été modifiée pour la última vez. Una vez que FunctionScope estuvo terminado, volvimos al alcance del script donde $ MyVar no fue tocado por la función. Luego, cuando terminó el guión, volvimos al alcance global donde no se había cambiado en absoluto.
Alcance fuera del alcance local
Entonces, todo esto está bien para ayudarlo a evitar la aplicación accidental de cambios al entorno más allá de sus scripts y funciones, pero ¿qué sucede si realmente desea realizar dichos cambios? Existe una sintaxis especial y bastante sencilla para crear y modificar objetos más allá del ámbito local. Simplemente coloque el nombre del alcance al principio del nombre de la variable y coloque dos puntos entre el alcance y los nombres de las variables. Así:
$global:MyVar $script:MyVar $local:MyVar
Puede utilizar estos modificadores al visualizar y configurar variables. Veamos qué sucede con este script de demostración:
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" ''
Como antes, comenzaremos estableciendo la variable en el alcance global y terminaremos verificando el resultado final del alcance global.
Aquí puede ver que FunctionScope pudo modificar la variable dentro del alcance del script y que los cambios persisten cuando se completan. Además, el cambio de alcance global de la variable persistió incluso después de cerrar el script. Esto puede ser especialmente útil si necesita modificar repetidamente variables en un script, o en el alcance global, usando el mismo código; simplemente defina una función o un script escrito para modificar la variable dónde y cómo lo necesite, e invoque siempre que se necesiten estos cambios.
Como se mencionó anteriormente, los números de alcance también se pueden usar en algunos comandos para cambiar la variable en diferentes niveles en relación con el alcance local. Aquí está el mismo script usado en el segundo ejemplo anterior, pero con la función modificada para usar los comandos Get-Variable y Set-Variable con números de alcance en lugar de hacer referencia directa a la variable con alcances con nombre:
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" ''
Al igual que antes, aquí podemos ver cómo los comandos en un alcance pueden modificar objetos en su alcance padre.
Información adicional
Todavía hay mucho más por hacer con los osciloscopios de lo que se puede encontrar en este artículo. Los ámbitos afectan más que solo las variables, y hay más que aprender sobre los ámbitos privados y las variables de AllScope. Para obtener más información útil, puede ejecutar el siguiente comando desde PowerShell:
Get-Help about_scopes
El mismo archivo de ayuda también está disponible en TechNet.
Crédito de la imagen de la camada: espadachín en openclipart