Cómo afectan los ámbitos a los scripts de PowerShell
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, lo contrario es cierto porque los ámbitos se utilizan para aislar las modificaciones de un script. Aquí, exploraremos cómo los ámbitos afectan 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 dentro del entorno para que no sean modificados involuntariamente por scripts o funciones. En particular, las siguientes cosas están protegidas contra modificaciones por comandos ejecutados desde otro ámbito, a menos que los parámetros especifiquen lo contrario en esos comandos:
- Variables
- Alias
- Funciones
- Unidades PowerShell (PSDrives)
Los nuevos ámbitos se crean cada vez que ejecuta un script 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 / secundaria" con el ámbito desde el que se crearon. Hay algunos ámbitos que tienen significados particularmente especiales, y se puede acceder a ellos por su nombre:
- los Global ámbito es el ámbito que se crea cuando se inicia PowerShell. Incluye las variables, alias, funciones y PSDrives que están incorporados en PowerShell, así como cualquiera que esté hecho por su perfil de PowerShell..
- los Local El alcance se refiere a lo que sea el alcance actual. Cuando inicie PowerShell, se referirá al ámbito global, dentro de un script será el ámbito del script, etc..
- los Guión El alcance se crea cuando se ejecuta un script. Los únicos comandos que operan dentro de este alcance son los que están en el script.
- Privado los ámbitos se pueden definir dentro del ámbito actual, para evitar que los comandos en otros ámbitos puedan leer o modificar elementos a los que de otro modo podrían tener acceso.
También se puede hacer referencia a los ámbitos por número en ciertos comandos, donde el ámbito actual se denomina cero y se hace referencia a sus ancestros al aumentar los enteros. Por ejemplo, dentro de un script ejecutado desde el ámbito Global, el alcance del Script sería 0 y el alcance Global sería 1. Un alcance que se anidó aún más dentro del alcance del Script, como una función, se referiría al alcance Global como 2 Sin embargo, los números negativos no servirán para hacer referencia a los ámbitos secundarios: la razón de esto será evidente en breve.
Cómo afectan los ámbitos a los comandos
Como se mencionó anteriormente, los comandos ejecutados dentro de un alcance no afectarán las cosas en otro alcance a menos que se indique específicamente que lo haga. Por ejemplo, si $ MyVar existe en el ámbito global y un script ejecuta un comando para configurar $ MyVar en un valor diferente, la versión global de $ MyVar permanecerá inalterada mientras se coloca una copia de $ MyVar en el ámbito del script con el nuevo valor. Si no existe un $ MyVar, un script lo creará dentro del ámbito del Script de forma predeterminada, no en el ámbito Global. Es importante recordar esto a medida que aprende sobre la relación real entre padres e hijos entre los ámbitos..
La relación padre / hijo de los ámbitos en PowerShell es unidireccional. Los comandos pueden ver y, opcionalmente, modificar el ámbito actual, su principal y cualquier ámbito por encima de eso. Sin embargo, no pueden ver ni modificar cosas en ningún elemento secundario del ámbito actual. Esto se debe principalmente a que, una vez que se ha movido a un ámbito principal, el ámbito secundario ya se ha destruido porque ha cumplido su propósito. Por ejemplo, ¿por qué tendría que ver o modificar una variable en el ámbito del script, desde el ámbito global, después de que el script haya terminado? Hay muchos casos en los que necesita que los cambios de una secuencia de comandos o una función persistan más allá de su finalización, pero no tantos en los que tendría que realizar cambios en los objetos dentro del alcance de la secuencia de comandos o de la función antes o después de su ejecución. (Por lo general, estas cosas se manejarán como parte de la secuencia de comandos o la función misma 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 los ámbitos privados solo son accesibles para los comandos que se ejecutan en el ámbito desde el que se crearon. Otra excepción importante son los elementos que tienen la propiedad AllScope. Estas son variables especiales y alias para los cuales un cambio en 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 | Donde-Objeto $ _. Opciones -configurar 'AllScope')
Ámbitos en acción
En nuestro primer vistazo a los ámbitos en acción, comenzaremos en una sesión de PowerShell en la que la variable $ MyVar se configuró en una cadena, '¡Soy una variable global!', Desde la línea de comandos. Luego, la siguiente secuencia de comandos se ejecutará desde un archivo llamado Scope-Demo.ps1:
Function FunctionScope 'Cambiar $ MyVar con una función'. $ MyVar = '¡Me fijé por una función!' "MyVar dice $ MyVar" "Comprobando el valor actual de $ MyVar". "MyVar dice $ MyVar" "Cambiando $ MyVar por script. ' $ MyVar = '¡Me fijé por un script!' "MyVar dice $ MyVar" "FunctionScope" Comprobando el valor final de MyVar antes de salir del script. ' "MyVar dice $ MyVar" "
Si los scripts de PowerShell funcionaran igual que los scripts de lotes, esperaríamos que el valor de $ MyVar (o% MyVar% en la sintaxis de lotes) cambie de "¡Soy una variable global!" A "¡Me estableció un script!" , y finalmente a '¡Me fijé por una función!' donde permanecería hasta que se cambie de nuevo explícitamente o se termine la sesión. Sin embargo, vea lo que realmente sucede aquí cuando nos movemos a través de cada uno de los ámbitos, en particular, después de que la función FunctionScope haya completado su trabajo y verifiquemos la variable nuevamente desde el Script, y luego el alcance Global,.
Como puede ver, la variable pareció cambiar a medida que avanzábamos en el script porque, hasta que se completó la función FunctionScope, comprobamos la variable desde el mismo ámbito en el que se modificó por última vez. Sin embargo, una vez que se realizó FunctionScope, regresamos al ámbito del Script donde la función no afectó a $ MyVar. Luego, cuando el script terminó, regresamos al ámbito global donde no se había modificado en absoluto..
Alcanzando fuera del alcance local
Entonces, todo esto está muy bien para ayudarlo a evitar la aplicación accidental de cambios en el entorno más allá de sus scripts y funciones, pero ¿qué sucede si realmente desea realizar dichas modificaciones? Hay una sintaxis especial y bastante simple para crear y modificar objetos más allá del alcance local. Simplemente coloque el nombre del ámbito al comienzo del nombre de la variable y coloque dos puntos entre los nombres del ámbito y la variable. Me gusta esto:
$ global: MyVar $ script: MyVar $ local: MyVar
Puede utilizar estos modificadores tanto al ver como a la configuración de variables. Veamos que pasa con este script de demostración:
Function FunctionScope "Cambiando $ MyVar en el alcance de la función local ... '$ local: MyVar =" Esta es MyVar en el alcance local de la función. "' Cambiando $ MyVar en el alcance del script ... '$ script: MyVar =' MyVar solía ser establecido por un script. Ahora establecido por una función. "Cambiando $ MyVar en el ámbito global ... '$ global: MyVar =' MyVar se estableció en el alcance global. Ahora establecido por una función. "Comprobando $ MyVar en cada ámbito ... '" Local: $ local: MyVar "" Script: $ script: MyVar "" Global: $ global: MyVar "" "Obteniendo el valor actual de $ MyVar.' "MyVar dice $ MyVar" "Cambiando $ MyVar por script. ' $ MyVar = '¡Me fijé por un script!' "MyVar dice $ MyVar" FunctionScope 'Comprobando $ MyVar desde el alcance del script antes de salir.' "MyVar dice $ MyVar" "
Como antes, comenzaremos por establecer la variable en el alcance Global y terminar con la verificación del resultado final del alcance Global.
Aquí puede ver que FunctionScope pudo cambiar la variable en el alcance del Script y que los cambios persisten una vez que se completó. Además, el cambio a la variable en el ámbito global persistió incluso después de que el script hubiera salido. Esto puede ser particularmente útil si tiene que cambiar repetidamente las variables dentro de un script, o dentro del alcance Global, usando el mismo código: simplemente define una función o script que está escrito para modificar la variable dónde y cómo lo necesita, y llamar a que siempre que los cambios son necesarios.
Como se mencionó anteriormente, los números de alcance también se pueden usar en ciertos comandos para modificar la variable en diferentes niveles en relación con el alcance local. Esta es la misma secuencia de comandos utilizada 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 ámbitos con nombre:
Function FunctionScope "Cambiando $ MyVar en el alcance 0, en relación con FunctionScope ... 'Set-Variable MyVar" Esta es MyVar en el alcance de la función 0. "-Scope 0' Cambiando $ MyVar en el alcance 1, en relación con FunctionScope ... 'Set-Variable MyVar 'MyVar se cambió en el alcance 1, desde una función'. -Scope 1 'Cambiando $ MyVar en el alcance 2, en relación con Functionscope ...' Set-Variable MyVar 'MyVar se cambió en el alcance 2, desde una función'. -Scope 2 "Comprobando $ MyVar en cada alcance ..." Alcance 0: 'Get-Variable MyVar -Scope 0 -ValueOnly' Alcance 1: 'Get-Variable MyVar -Scope 1 -ValueOnly' Scope 2: 'Get-Variable MyVar -Scope 2 -ValueOnly "" Obteniendo el valor actual de $ MyVar. ' "MyVar dice $ MyVar" "Cambiando $ MyVar por script. ' $ MyVar = '¡Me fijé por un script!' "MyVar dice $ MyVar" FunctionScope 'Comprobando $ MyVar desde el alcance del script antes de salir.' "MyVar dice $ MyVar" "
Al igual que antes, podemos ver aquí cómo los comandos en un ámbito pueden modificar objetos en su ámbito primario.
Información Adicional
Todavía se puede hacer mucho más con los ámbitos de los que caben en este artículo. Los ámbitos afectan más que solo las variables, y aún hay más que aprender acerca de los ámbitos privados y las variables de AllScope. Para obtener más información útil, puede ejecutar el siguiente comando desde PowerShell:
Obtener ayuda sobre about_scopes
El mismo archivo de ayuda también está disponible en TechNet..
Crédito de la imagen del alcance: spadassin en openclipart