Adam el Automatizador

author
15 minutes, 0 seconds Read

Cuando escribes un script de PowerShell sin funciones y sin dependencias externas de otros scripts, el concepto de ámbitos de PowerShell no es de mucha preocupación. El concepto de variables globales de PowerShell no es frontal y central. Pero a medida que empiezas a construir funciones, módulos y aprendes a llamar a scripts desde otros scripts, el tema se vuelve más importante.

En este artículo, vas a recibir una lección profunda sobre lo que son los ámbitos en PowerShell, cómo funcionan y cómo puedes escribir código teniendo en cuenta los ámbitos. Cuando termines, entenderás las variables globales de PowerShell y mucho más!

Tabla de contenidos

Ámbitos: Algo así como cubos

¿Has escrito alguna vez un script en el que defines una variable y cuando compruebas el valor de esa variable, es otra cosa? Puede que te rasques la cabeza al ver cómo ha cambiado esa variable cuando la has definido claramente. Una de las razones puede ser que el valor de la variable se está sobrescribiendo en otro ámbito.

Tal vez te hayas preguntado cómo ciertas variables de PowerShell tienen valores cuando las referencias en tu consola pero no existen en tus scripts. Lo más probable es que esas variables estén en otro ‘cubo’ que no está disponible en ese momento.

Los ámbitos son como cubos. Los ámbitos afectan a la forma en que PowerShell aísla las variables, los alias, las funciones y los PSDrives entre diferentes áreas. Un ámbito es como un cubo. Es un lugar para recoger todos estos elementos juntos.

Cuando PowerShell se inicia, crea automáticamente estos «cubos» para usted. En ese momento, ya estás usando scopes sin darte cuenta. Todos los ámbitos son definidos por PowerShell y se crean sin ninguna ayuda de tu parte.

Tipos de Ámbito

Cuando PowerShell se inicia, crea automáticamente cuatro «cubos» o ámbitos para colocar varios elementos. Usted no puede crear ámbitos por su cuenta. Sólo puede añadir y eliminar elementos de estos ámbitos definidos a continuación.

Ámbito global

Los elementos definidos cuando se abre PowerShell se establecen en el ámbito global. Estos elementos incluyen objetos creados por el sistema como unidades de PowerShell y también cualquier cosa que haya definido en un perfil de PowerShell ya que su perfil se ejecuta al inicio.

Los elementos del ámbito global están disponibles en todas partes. Puede hacer referencia a los elementos del ámbito global de forma interactiva en la consola, en cualquier script que ejecute y en cualquier función. Las variables globales de PowerShell están en todas partes. Por esta razón, el uso común de las variables globales de PowerShell es utilizar las variables globales de PowerShell entre scripts.

Sólo hay un ámbito global que rige en general.

Ámbito de script

Un ámbito de script se crea automáticamente cada vez que se ejecuta un script de PowerShell. Puede tener muchas instancias de ámbito de script diferentes. Los ámbitos de script se crean cuando se ejecuta un script PS1 o un módulo, por ejemplo.

Sólo los elementos creados en esa instancia de ámbito de script particular pueden hacer referencia a los demás.

Ámbito privado

Típicamente, se puede acceder a un elemento definido desde otros ámbitos – no es cierto con los elementos de un ámbito privado. Los elementos en un ámbito privado, contienen objetos que están ocultos a otros ámbitos. Un ámbito privado se utiliza para crear elementos con el mismo nombre que los elementos en otros ámbitos para evitar la superposición.

Ámbito local

A diferencia de los otros ámbitos, el ámbito local es un poco diferente. El ámbito local es un puntero al ámbito global, script o privado. El ámbito local es relativo a cualquier contexto en el que se ejecute el código en ese momento.

Si creas una variable, un alias, una función o un PSDrive sin asignarle explícitamente un ámbito (lo que veremos más adelante) irá al ámbito local.

Referenciando Ámbitos

Ahora que tienes una idea de los cuatro tipos de ámbitos que existen, también debes saber que hay dos formas de referenciar esos ámbitos.

En PowerShell, hay dos formas de referenciar ámbitos – con nombre o numerados. Ambos métodos están haciendo referencia a los mismos ámbitos, pero simplemente de una manera diferente. Estas son dos formas diferentes de interactuar con los ámbitos.

Ámbitos con nombre

Antes, en la sección Tipo de Ámbito, aprendiste sobre los ámbitos referenciados por nombre. Referenciar un ámbito por nombre se llama, intuitivamente, un ámbito con nombre. El propósito principal de referenciar un ámbito por nombre es asignar un elemento a un ámbito. Aprenderás cómo hacer esto a continuación.

Ámbitos numerados

Además de un nombre, cada ámbito tiene un número que comienza en cero y que siempre será el ámbito local. Los ámbitos se numeran dinámicamente en relación con el ámbito local actual.

Por ejemplo, en cuanto se abre una sesión de PowerShell se opera en el ámbito global. En este punto, el ámbito global es el ámbito local (recuerde que el ámbito local es sólo un puntero).

Como el ámbito local es siempre el ámbito cero, en este punto, el ámbito global es también actualmente el ámbito cero. Pero, cuando se ejecuta un script desde esa misma sesión, se crea un ámbito de script. Cuando se ejecuta, el puntero del ámbito local ha cambiado al ámbito del script. Ahora el ámbito de la secuencia de comandos es el ámbito cero y el ámbito global es el ámbito uno.

Los ámbitos se numeran Este proceso se repite para tantos ámbitos como tenga donde el ámbito local sea 0. Los ámbitos se numeran dinámicamente por jerarquía de ámbito.

Jerarquía de Ámbito y Herencia

Como se mencionó anteriormente, cuando se inicia una sesión de PowerShell, PowerShell crea algunos elementos para usted en el ámbito global. Estos elementos pueden ser funciones, variables, aliases o PSDrives. Cualquier cosa que defina en su sesión de PowerShell se definirá también en el ámbito global.

Dado que está en el ámbito global por defecto, si hace algo que crea otro ámbito como ejecutar un script o ejecutar una función, se creará un ámbito hijo cuyo padre es el ámbito global. Los ámbitos son como procesos con padres e hijos.

Cualquier cosa que se defina en un ámbito padre, el ámbito global, en este caso, será accesible en el ámbito hijo. Pero estos elementos sólo son editables en el ámbito en el que fueron definidos.

Digamos que tienes un script llamado Test.ps1. Dentro de este script hay una sola línea como se muestra a continuación.

$a = 'Hello world!'

Cuando se ejecuta este script, a $a se le asigna un valor en el ámbito local (script mientras se ejecuta el script). Cuando se ejecuta Test.ps1, se puede ver a continuación que no se puede hacer referencia a él después de que se ejecute el script. Dado que $a fue asignada mientras estaba en el ámbito del script, el ámbito global (en la consola interactiva) no puede verla.

El ámbito global no puede ver la variable

Llevemos este ejemplo un paso más allá y hagamos que el script Test.ps1 tenga el siguiente aspecto. El script ahora está intentando dar salida al valor de $a antes de establecerlo en el mismo ámbito.

Write-Output $a$a = 'Hello world!'

Para demostrarlo, asigne un valor a $a en la consola interactiva. Esto asigna el valor en el ámbito global. Ahora, el script se ejecuta, heredará el ámbito padre (global) y debería ser capaz de ver el valor.

Puede ver a continuación que cuando Test.ps1 se ejecuta (creando un ámbito hijo del ámbito global), puede ver el valor de $a. También puede ver que el valor de la variable está disponible en el ámbito global también ya que este ámbito es donde se estableció. Esto significa que $a está disponible tanto en el ámbito script (hijo) como en el ámbito padre (global).

La variable está disponible en los ámbitos script y global

Recuerde este comportamiento de herencia de ámbitos. Haciendo esto le ayudará cuando se produzcan conflictos de variables en la resolución de problemas, tales como variables en diferentes ámbitos con el mismo nombre.

Definiendo y accediendo a elementos en ámbitos

Ahora que sabe lo que es un ámbito y cómo funcionan, ¿cómo se accede a ellos? Veamos cómo usar PowerShell para establecer un ámbito de variables (y acceder a ellas).

Get/Set-Variable

En PowerShell, hay dos cmdlets que permiten establecer variables llamados Get-Variable y Set-Variable. Estos cmdlets permiten recuperar el valor de una variable o definir un valor.

Ambos cmdlets son similares con un parámetro Name y Scope. Utilizando estos parámetros, PowerShell permite establecer y recuperar valores de variables en todos los ámbitos.

Ámbitos locales

Para establecer una variable en un ámbito local, utilice Set-Variable y proporciónele un nombre de variable local y un valor como se muestra a continuación.

PS> Set-Variable -Name a -Value 'foo'

El ámbito local es siempre el predeterminado, por lo que si no se utiliza el parámetro Scope siempre se definirá la variable en el ámbito local.

Para recuperar el valor de una variable de ámbito local, utiliza Get-Variable proporcionándole el nombre.

PS> Get-Variable -Name aName Value---- -----a foo

Ámbitos privado/script/global

También utilizarás los mismos parámetros (Name y Value) cuando trabajes con variables privadas, de script y globales. La única diferencia es que esta vez utilizarás el parámetro Scope para definir explícitamente el ámbito.

Los métodos para establecer una variable privada, de script o de ámbito global son los mismos. Simplemente reemplaza el valor pasado al parámetro Scope como Private, Script Global.

PS> Set-Variable -Name a -Value 'foo' -Scope <Private|Script|Global>

Para recuperar el valor de una variable de script o de ámbito global, utiliza Get-Variable proporcionándole el nombre y el ámbito.

PS> Get-Variable -Name a -Scope <Script|Global>Name Value---- -----a foo

Nota: También se puede hacer referencia a los ámbitos utilizando números de ámbito en lugar de nombres con los cmdlets Get/Set-Variable.

Ámbito «Prefacio»

También se pueden recuperar y establecer variables en ámbitos utilizando un acceso directo. En lugar de utilizar los cmdlets de PowerShell, prefigurará el ámbito a la variable al referenciarla.

Ámbitos locales

Como el ámbito local es siempre el predeterminado, simplemente definiendo una variable y haciendo referencia a ella establecerá y recuperará una variable de ámbito local

PS> $a = 'foo'PS> $afoo

Ámbitos privados/script/global

Si desea definir y hacer referencia a ámbitos de script o globales, puede anteponer a las variables el nombre del ámbito y un punto y coma.

Por ejemplo, para establecer la variable $a en el ámbito global, puede preceder a con $global:.

$global:a = 'foo'

Lo mismo se puede hacer para una variable de ámbito de script.

$script:a = 'foo'

Una vez que las variables se establecen en el ámbito preferido, entonces se hace referencia a ellos de la misma manera. Además, observe que puede excluir el prefijo de ámbito si el ámbito definido es el ámbito local.

PS> $global:a = 'foo'PS> $global:afooPS> $afoo

Ámbitos en Scriptblocks

PowerShell tiene una práctica construcción llamada scriptblocks. Los Scriptblocks te permiten mover fragmentos de código y ejecutarlos prácticamente en cualquier lugar.

Al igual que un script PS1, los scriptblocks se ejecutan en su propio ámbito de script. Cuando ejecutas un scriptblock, esencialmente estás ejecutando un script PS1.

Nota en el ejemplo de abajo donde se define una variable en el ámbito global y luego se intenta sobrescribir en un ámbito de script. Como aprendió anteriormente, esto no funcionará porque un ámbito hijo no puede hacer referencia a un ámbito padre.

Un ámbito hijo no puede sobrescribir un ámbito padre

Este ejemplo muestra que cuando $a se cambia en el bloque de script, la definición de la variable global para $a no se cambia porque el bloque de script es un ámbito hijo de script.

Scripts Dot Sourcing (Swapping Local Scopes)

PowerShell tiene un concepto llamado dot-sourcing. Este es un método que le permite ejecutar un script PS1 y traer todo lo que sería de ámbito de secuencia de comandos en el ámbito local en su lugar.

Poniendo un punto (.) antes de hacer referencia a un script PS1 y ejecutarlo, este «punto fuentes» el contenido de la secuencia de comandos y trae todo en el ámbito local.

Para demostrarlo, tengo un script Test.ps1 de nuevo que define una variable como se muestra a continuación.

$a = 'Hello world!'

En una consola de PowerShell, establezca un valor para una variable $a y luego haga dot source a este script como se muestra a continuación. Observe que la variable original fue sobrescrita. PowerShell «fusionó» los dos ámbitos locales juntos.

Variable original sobrescrita

Uso de la propiedad AllScope (Opción)

Ha visto cómo interactuar con elementos en ámbitos específicos, pero hasta ahora cada elemento sigue definido en un solo ámbito. Pero, ¿qué ocurre si no sabe en qué ámbito está definida una variable?

Al definir una variable con el cmdlet Set-Variable, puede colocar la variable en todos los ámbitos a la vez. Para ello, utilice el valor AllScope para el parámetro Option.

Para demostrarlo, se ha modificado el script Test.ps1 para establecer una variable en todos los ámbitos. Esa variable es entonces la salida como se muestra a continuación.

Set-Variable -Name a -Value 'Hello world!' -Option AllScopeWrite-Output $a

Puede entonces ver a continuación que se está estableciendo un valor para $a en el ámbito global y el script Test.ps1 se ejecuta. Sin embargo, en lugar de no tener efecto, el valor de $a ha sido sobrescrito. No sólo se ha definido en el ámbito del script (Write-Output $a) sino que también se ha sobrescrito el ámbito global.

Variable sobrescrita en el ámbito global

La opción AllScope es útil pero tenga cuidado. Esta opción esencialmente elimina el concepto de ámbitos y fusiona todo junto.

Ámbitos de función

Cuando se ejecuta una función, todo el código dentro de esa función está en su propio ámbito hijo. Los ámbitos de las funciones siguen el mismo comportamiento de hijo/padre que otros ámbitos.

Tener ámbitos separados para cada función es una buena idea. Permite un mejor control sobre los elementos sin tener que preocuparse por los elementos en conflicto, También da el beneficio añadido de la limpieza automatizada de las variables en una función. Tan pronto como la función se completa, todos los elementos definidos en la función se borrará.

Para demostrar, copiar / pegar la función de abajo directamente en la consola de PowerShell.

Function Do-Thing { $var = 'bar'}

Una vez pegado, ejecutar la función. Observe que no puede acceder a la variable $var fuera de la función.

PS> Do-ThingPS> $var

Mantener elementos privados (deshabilitar la herencia)

Típicamente, si una variable se define en un ámbito padre, esa variable se definirá en el ámbito hijo. Pero tal vez quiera utilizar un nombre de variable pero ese nombre de variable ya ha sido definido en uno de los ámbitos a ejecutar en una sesión. En ese caso, puedes elegir un nombre de variable diferente o definir la variable en un ámbito privado convirtiéndola en una variable privada.

Una forma de utilizar los ámbitos para reducir los conflictos es utilizar el ámbito privado. El uso del ámbito privado desactiva la herencia en esa variable específica. Cuando se crean múltiples ámbitos hijos, esos ámbitos hijos no verán ninguna variable definida en un ámbito privado.

Un script Test.ps1 saca el valor de $a como se muestra a continuación.

Write-Output $a

Puede ver a continuación que estoy definiendo una variable de ámbito privado en el ámbito global y luego ejecutando el script Test.ps1. Normalmente, cuando se define una variable en un ámbito padre, esa variable estará disponible en el ámbito hijo – no es así con una variable de ámbito privado.

En el siguiente ejemplo, se puede ver que el ámbito hijo del script creado al ejecutar el script Test.ps1 no podía ver la variable de ámbito privado $a definida en el ámbito padre.

El ámbito del script no puede ver la variable de ámbito privado

A diferencia de los ámbitos globales o de la opción AllScope del cmdlet Set-Variable, las variables de ámbito privado son una forma excelente de compartimentar elementos.

Mejores prácticas de ámbito

Es común pensar que definir variables en el ámbito global o utilizar la opción AllScope es el camino a seguir. Después de todo, todas las variables están disponibles en todas partes. No hay necesidad de preocuparse por las complicaciones de los ámbitos. Aunque esto proporciona una libertad adicional para el acceso a lo que se define, puede salirse rápidamente de control y ser difícil de solucionar.

En lugar de tratar de evitar el uso de ámbitos siga estos consejos:

  1. En lugar de especificar ámbitos en las funciones, utilice parámetros para pasar la información necesaria a la función.
  2. Manténgase dentro del ámbito local tanto como sea posible.
  3. En lugar de definir variables globales desde un script, utilice el cmdlet Write-Outputpara que salga todo y se guarde en una variable cuando se necesite desde la consola.

El punto principal aquí es abrazar los ámbitos y aprender a usarlos para su ventaja en lugar de tratar de eludirlos.

Lectura adicional

  • Acerca de las funciones avanzadas y parámetros de función
  • Uso de variables de entorno en PowerShell

Similar Posts

Deja una respuesta

Tu dirección de correo electrónico no será publicada.