Compartir a través de


acerca_de_Scopes

Descripción breve

Explica el concepto de ámbito en PowerShell y muestra cómo establecer y cambiar el ámbito de los elementos.

Descripción larga

PowerShell protege el acceso a variables, alias, funciones y unidades de PowerShell (PSDrive) limitando dónde se pueden leer y cambiar. PowerShell usa reglas de ámbito para asegurarse de que no se cambia inadvertidamente un elemento que no se debe cambiar.

A continuación se muestran las reglas básicas del ámbito:

  • Los ámbitos pueden anidarse. Un ámbito externo se conoce como ámbito primario. Los ámbitos anidados son ámbitos secundarios de ese ámbito principal.

  • Un elemento es visible en el ámbito en el que se creó y en los ámbitos secundarios, a menos que lo convierta explícitamente en privado.

  • Puede declarar variables, alias, funciones y unidades de PowerShell en un ámbito fuera del ámbito actual.

  • Un elemento que creó dentro de un ámbito solo se puede cambiar en el ámbito en el que se creó, a menos que especifique explícitamente un ámbito diferente.

Si crea un elemento en un ámbito y el elemento comparte su nombre con un elemento de un ámbito diferente, es posible que el elemento original esté oculto en el nuevo elemento, pero no se invalida ni se cambia.

Ámbitos de PowerShell

PowerShell admite los siguientes ámbitos:

  • Global: el ámbito que está en vigor cuando se inicia PowerShell o cuando se crea una nueva sesión o espacio de ejecución. Las variables y funciones que están presentes cuando se inicia PowerShell se han creado en el ámbito global, como las variables automáticas y las variables de preferencia. Las variables, alias y funciones de los perfiles de PowerShell también se crean en el ámbito global. El ámbito global es el ámbito primario raíz de una sesión.

  • Local: el ámbito actual. El ámbito local puede ser el ámbito global o cualquier otro ámbito.

  • Script: el ámbito que se crea mientras se ejecuta un archivo de script. Solo los comandos de la secuencia de comandos se ejecutan en el ámbito de la secuencia de comandos. Para los comandos de un script, el ámbito del script es el ámbito local.

Nota:

Privado no es un ámbito. Es una opción que cambia la visibilidad de un elemento fuera del ámbito en el que se define el elemento.

Ámbitos primario y secundario

Puede crear un nuevo ámbito secundario llamando a un script o función. El ámbito de llamada es el ámbito principal. El script o función llamados son el ámbito secundario. Las funciones o scripts que llame pueden llamar a otras funciones, lo que crea una jerarquía de ámbitos secundarios cuyo ámbito raíz es el ámbito global.

A menos que haga explícitamente que los elementos sean privados, los elementos del ámbito principal están disponibles para el ámbito secundario. Sin embargo, los elementos que se crean y cambian en el ámbito secundario no afectan al ámbito primario, a menos que se especifique explícitamente el ámbito al crear los elementos.

Nota:

Las funciones de un módulo no se ejecutan en un ámbito secundario del ámbito de llamada. Los módulos tienen su propio estado de sesión que está vinculado al ámbito global. Todo el código de módulo se ejecuta en una jerarquía específica del módulo de ámbitos que tiene su propio ámbito raíz.

Herencia

Un ámbito secundario no hereda las variables, los alias y las funciones del ámbito primario. A menos que un elemento sea privado, el ámbito secundario puede ver los elementos del ámbito primario. Además, puede cambiar los elementos especificando explícitamente el ámbito primario, pero los elementos no forman parte del ámbito secundario.

Sin embargo, se crea un ámbito secundario con un conjunto de elementos. Normalmente, incluye todos los alias que tienen la opción AllScope . Esta opción se describe más adelante en este artículo. Incluye todas las variables que tienen la opción AllScope , además de algunas variables automáticas.

Para buscar los elementos en un ámbito determinado, use el parámetro Scope de Get-Variable o Get-Alias.

Por ejemplo, para obtener todas las variables del ámbito local, escriba:

Get-Variable -Scope local

Para obtener todas las variables del ámbito global, escriba:

Get-Variable -Scope global

Modificadores de alcance

Una variable, alias o nombre de función puede incluir cualquiera de los siguientes modificadores de ámbito opcionales:

  • global:: especifica que el nombre existe en el ámbito global.

  • local:: especifica que el nombre existe en el ámbito local. El ámbito actual es siempre el ámbito local.

  • private:: especifica que el nombre es privado y solo es visible para el ámbito actual.

  • script:: Indica que el nombre existe en el ámbito de Script. El ámbito del script es el del archivo de script antecesor más cercano o Global si no hay ningún archivo de script antecesor más cercano.

  • using: - Se usa para acceder a variables definidas en otro ámbito mientras se ejecutan scripts a través de cmdlets como Start-Job y Invoke-Command.

  • workflow:: especifica que el nombre existe dentro de un flujo de trabajo. Nota: Los flujos de trabajo no se admiten en PowerShell v6 y versiones posteriores.

  • <variable-namespace> - Un modificador creado por un proveedor de PSDrive de PowerShell. Por ejemplo:

    Namespace Descripción
    Alias: Alias definidos en el ámbito actual
    Env: Variables de entorno definidas en el ámbito actual
    Function: Funciones definidas en el ámbito actual
    Variable: Variables definidas en el ámbito actual

El ámbito predeterminado de los scripts es el ámbito de script. El ámbito predeterminado para las funciones y los alias es el ámbito local, incluso si están definidos en un script.

Uso de modificadores de ámbito

Para especificar el ámbito de una nueva variable, alias o función, use un modificador de ámbito.

La sintaxis de un modificador de ámbito en una variable es:

$[<scope-modifier>:]<name> = <value>

La sintaxis de un modificador de ámbito en una función es:

function [<scope-modifier>:]<name> {<function-body>}

El siguiente comando, que no utiliza un modificador de ámbito, crea una variable en el ámbito actual o local :

$a = "one"

Para crear la misma variable en el ámbito global de , use el modificador de ámbito global::

$global:a = "one"

Para crear la misma variable dentro del ámbito del script , use el modificador de ámbito script::

$script:a = "one"

También puede usar un modificador de ámbito con funciones. La siguiente definición de función crea una función en el ámbito global:

function global:Hello {
  Write-Host "Hello, World"
}

También puede usar modificadores de ámbito para hacer referencia a una variable en un ámbito diferente. El siguiente comando hace referencia a la variable $test, primero en el ámbito local y, a continuación, en el ámbito global:

$test
$global:test

Modificador de ámbito Using:

Using es un modificador de ámbito especial que identifica una variable local en un comando remoto. Sin un modificador, PowerShell espera que las variables de los comandos remotos se definan en la sesión remota.

El modificador de ámbito Using se introduce en PowerShell 3.0.

Para cualquier script o comando que se ejecute fuera de sesión, necesita el modificador de ámbito Using para insertar valores de variables del ámbito de la sesión que realiza la llamada, de modo que el código fuera de sesión pueda acceder a ellos. El modificador de ámbito Using se admite en los contextos siguientes:

  • Comandos ejecutados de forma remota, iniciados con Invoke-Command mediante el ComputerName, HostName, SSHConnection o los parámetros Session (sesión remota)
  • Trabajos en segundo plano, iniciados con Start-Job (sesión fuera del proceso)
  • Trabajos de hilo, iniciados a través de Start-ThreadJob o ForEach-Object -Parallel (sesión de hilo independiente)

Dependiendo del contexto, los valores de las variables incrustadas son copias independientes de los datos en el ámbito del llamante o referencias a los mismos. En las sesiones remotas y fuera de proceso, siempre son copias independientes.

Para obtener más información, vea about_Remote_Variables.

En sesiones de subprocesos, se pasan por referencia. Esto significa que es posible modificar las variables de ámbito de llamada en un subproceso diferente. Para modificar variables de forma segura, se requiere sincronización de subprocesos.

Para obtener más información, vea:

Serialización de valores de variable

Los comandos ejecutados de forma remota y los trabajos en segundo plano se ejecutan fuera de proceso. Las sesiones fuera de proceso usan la serialización y deserialización basada en XML para que los valores de las variables estén disponibles en los límites del proceso. El proceso de serialización convierte objetos en un PSObject que contiene las propiedades de los objetos originales, pero no sus métodos.

Para un conjunto limitado de tipos, la deserialización rehidrata los objetos al tipo original. El objeto rehidratado es una copia de la instancia de objeto original. Posee propiedades y métodos de tipo. Para tipos simples, como System.Version, la copia es exacta. En el caso de tipos complejos, la copia es imperfecta. Por ejemplo, los objetos de certificado rehidratados no incluyen la clave privada.

Las instancias de todos los demás tipos son del tipo PSObject. La propiedad PSTypeNames contiene el nombre de tipo original con el prefijo Deserialized, por ejemplo, Deserialized.System.Data.DataTable

Opción AllScope

Las variables y alias tienen una propiedad Option que puede tomar un valor de AllScope. Los elementos que tienen la propiedad AllScope pasan a formar parte de los ámbitos secundarios que cree, aunque los ámbitos primarios no los heredan retroactivamente.

Un elemento que tiene la propiedad AllScope es visible en el ámbito secundario y forma parte de ese ámbito. Los cambios en el elemento de cualquier ámbito afectan a todos los ámbitos en los que se define la variable.

Gestión del alcance

Varios cmdlets tienen un parámetro Scope que permite obtener o establecer (crear y cambiar) elementos en un ámbito determinado. Utiliza el siguiente comando para buscar todos los cmdlets en tu sesión que tienen un parámetro de Scope:

Get-Help * -Parameter scope

Para buscar las variables que están visibles en un ámbito determinado, use el parámetro Scope de Get-Variable. Las variables visibles incluyen variables globales, variables en el ámbito primario y variables en el ámbito actual.

Por ejemplo, el siguiente comando obtiene las variables visibles en el ámbito local:

Get-Variable -Scope local

Para crear una variable en un ámbito determinado, use un modificador de ámbito o el parámetro Scope de Set-Variable. El comando siguiente crea una variable en el ámbito global:

New-Variable -Scope global -Name a -Value "One"

También puede usar el parámetro Scope de los cmdlets New-Alias, Set-Aliaso Get-Alias para especificar el ámbito. El comando siguiente crea un alias en el ámbito global:

New-Alias -Scope global -Name np -Value Notepad.exe

Para obtener las funciones en un ámbito determinado, use el cmdlet Get-Item cuando se encuentre en dicho ámbito. El Get-Item cmdlet no tiene un parámetro Scope .

Nota:

Para los cmdlets que usan el parámetro Scope, también puede hacer referencia a los ámbitos por número. El número describe la posición relativa de un ámbito a otro. El ámbito 0 representa el ámbito actual o local. El ámbito 1 indica el ámbito principal inmediato. El ámbito 2 indica el ámbito principal del ámbito principal, y así sucesivamente. Los ámbitos numerados son útiles si ha creado muchos ámbitos recursivos.

Uso de la notación de origen de puntos con ámbito

Los scripts y las funciones siguen todas las reglas de ámbito. Los crea en un ámbito determinado y solo afectan a ese ámbito, a menos que use un parámetro de cmdlet o un modificador de ámbito para cambiar ese ámbito.

Sin embargo, puede agregar un script o una función al ámbito actual mediante la notación de origen de puntos. A continuación, cuando se ejecuta un script en el ámbito actual, las funciones, alias y variables que crea el script están disponibles en el ámbito actual.

Para agregar una función al ámbito actual, escriba un punto (.) y un espacio antes de la ruta de acceso y el nombre de la función en la llamada a la función.

Por ejemplo, para ejecutar el script Sample.ps1 desde el directorio C:\Scripts en el ámbito del script (el valor predeterminado para los scripts), use el siguiente comando:

c:\scripts\sample.ps1

Para ejecutar el script Sample.ps1 en el ámbito local, use el siguiente comando:

. c:\scripts.sample.ps1

Cuando se usa el operador de llamada (&) para ejecutar una función o script, no se agrega al ámbito actual. En el ejemplo siguiente se utiliza el operador de llamada:

& c:\scripts.sample.ps1

Puede leer más sobre el operador de llamadas en about_operators.

Los alias, funciones o variables que crea el script Sample.ps1 no están disponibles en el ámbito actual.

Restringir sin ámbito de aplicación

Algunos conceptos de PowerShell son similares al ámbito o interactúan con el ámbito. Estos conceptos pueden confundirse con el ámbito o el comportamiento del ámbito.

Las sesiones, los módulos y las peticiones de datos anidadas son entornos independientes, pero no son ámbitos secundarios del ámbito global de la sesión.

Sesiones

Una sesión es un entorno en el que se ejecuta PowerShell. Al crear una sesión en un equipo remoto, PowerShell establece una conexión persistente al equipo remoto. La conexión persistente le permite usar la sesión para varios comandos relacionados.

Dado que una sesión es un entorno contenido, tiene su propio ámbito, pero una sesión no es un ámbito secundario de la sesión en la que se creó. La sesión comienza con su propio ámbito global. Este ámbito es independiente del ámbito global de la sesión. Puede crear ámbitos secundarios en la sesión. Por ejemplo, puede ejecutar un script para crear un ámbito secundario durante una sesión.

Módulos

Puede usar un módulo de PowerShell para compartir y entregar herramientas de PowerShell. Un módulo es una unidad que puede contener cmdlets, scripts, funciones, variables, alias y otros elementos útiles. A menos que se defina explícitamente, no se puede acceder a los elementos de un módulo fuera del módulo. Por lo tanto, puede agregar el módulo a la sesión y usar los elementos públicos sin preocuparse de que los demás elementos podrían invalidar los cmdlets, scripts, funciones y otros elementos de la sesión.

De forma predeterminada, los módulos se cargan en el nivel superior del estado de sesión actual, no en el ámbito actual. El estado de sesión actual puede ser un estado de sesión de módulo o el estado de sesión global. Agregar un módulo a una sesión no cambia el alcance. Si se encuentra en el ámbito global, los módulos se cargan en el estado de sesión global. Las exportaciones se colocan en las tablas globales. Si carga module2 desde module1 , module2 se carga en el estado de sesión de module1, no en el estado de sesión global. Todas las exportaciones de module2 se colocan en la parte superior del estado de sesión module1. Si usa Import-Module -Scope local, las exportaciones se colocan en el objeto de ámbito actual en lugar de en el nivel superior. Si está en un módulo y usa Import-Module -Scope global (o Import-Module -Global) para cargar otro módulo, ese módulo y sus exportaciones se cargan en el estado de sesión global en lugar del estado de sesión local del módulo. Esta característica fue diseñada para escribir módulos que manipulan módulos. El módulo WindowsCompatibility hace esto para importar módulos proxy en el estado de sesión global.

Dentro del estado de sesión, los módulos tienen su propio ámbito. Tenga en cuenta el siguiente módulo C:\temp\mod1.psm1:

$a = "Hello"

function foo {
    "`$a = $a"
    "`$global:a = $global:a"
}

Ahora creamos una variable global $a, asígnele un valor y llame a la función foo.

$a = "Goodbye"
foo

El módulo declara la variable $a en el ámbito del módulo y, a continuación, la función foo genera el valor de la variable en ambos ámbitos.

$a = Hello
$global:a = Goodbye

Peticiones de datos anidadas

Las peticiones de datos anidadas no tienen su propio ámbito. Cuando se introduce una solicitud anidada, esa solicitud forma parte del entorno. Sin embargo, permanece dentro del ámbito local.

Los scripts tienen su propio ámbito. Si está depurando un script y llega a un punto de interrupción en el script, escriba el ámbito del script.

Opción Privada

Los alias y las variables tienen una propiedad Option que puede tomar un valor de Private. Los elementos que tienen la opción Privado se pueden ver y cambiar en el ámbito en el que se crean, pero no se pueden ver ni cambiar fuera de ese ámbito.

Por ejemplo, si crea una variable que tiene una opción privada en el ámbito global y, a continuación, ejecuta una secuencia de comandos, Get-Variable los comandos de la secuencia de comandos no muestran la variable privada. El uso del modificador de ámbito global en este caso no muestra la variable privada.

Puede usar el parámetro Option de los New-Variablecmdlets , Set-Variable, New-Aliasy Set-Alias para establecer el valor de la propiedad Option en Private.

Visibilidad

La propiedad Visibility de una variable o alias determina si puede ver el elemento fuera del contenedor, en el que se creó. Un contenedor podría ser un módulo, un script o un complemento. La visibilidad está diseñada para los contenedores de la misma manera que el valor Private de la propiedad Option está diseñado para los ámbitos.

La propiedad Visibility toma los valores Public y Private . Los elementos que tienen visibilidad privada solo se pueden ver y cambiar en el contenedor en el que se crearon. Si se agrega o importa el contenedor, los elementos que tienen visibilidad privada no se pueden ver ni cambiar.

Dado que la visibilidad está diseñada para contenedores, funciona de forma diferente en un ámbito.

  • Si crea un elemento que tiene visibilidad privada en el ámbito global, no podrá ver ni cambiar el elemento en ningún ámbito.
  • Si intenta ver o cambiar el valor de una variable que tiene visibilidad privada, PowerShell devuelve un mensaje de error.

Puede usar los cmdlets New-Variable y Set-Variable para crear una variable que tenga visibilidad privada.

Ejemplos

Ejemplo 1: Cambiar el valor de una variable solo en un script

El comando siguiente cambia el valor de la variable $ConfirmPreference en un script. El cambio no afecta al ámbito global.

En primer lugar, para mostrar el valor de la variable $ConfirmPreference en el ámbito local, use el siguiente comando:

PS>  $ConfirmPreference
High

Cree un script Scope.ps1 que contenga los siguientes comandos:

$ConfirmPreference = "Low"
"The value of `$ConfirmPreference is $ConfirmPreference."

Ejecute el script. El script cambia el valor de la variable $ConfirmPreference y, a continuación, informa de su valor en el ámbito del script. La salida debe ser similar a la siguiente salida:

The value of $ConfirmPreference is Low.

A continuación, pruebe el valor actual de la variable $ConfirmPreference en el ámbito actual.

PS>  $ConfirmPreference
High

En este ejemplo se muestra que los cambios en el valor de una variable en el ámbito del script no afectan al valor de la variable en el ámbito primario.

Ejemplo 2: Visualización de un valor de variable en diferentes ámbitos

Puede usar modificadores de ámbito para ver el valor de una variable en el ámbito local y en un ámbito primario.

En primer lugar, defina una variable $test en el ámbito global.

$test = "Global"

A continuación, cree un script Sample.ps1 que defina la variable $test. En el script, use un modificador de ámbito para hacer referencia a las versiones globales o locales de la variable $test.

En Sample.ps1:

$test = "Local"
"The local value of `$test is $test."
"The global value of `$test is $global:test."

Al ejecutar Sample.ps1, la salida debe ser similar a la siguiente salida:

The local value of $test is Local.
The global value of $test is Global.

Una vez completado el script, solo se define el valor global de $test en la sesión.

PS>  $test
Global

Ejemplo 3: Cambiar el valor de una variable en un ámbito primario

A menos que proteja un elemento mediante la opción Private u otro método, puede ver y cambiar el valor de una variable en un ámbito primario.

En primer lugar, defina una variable $test en el ámbito global.

$test = "Global"

A continuación, cree un script Sample.ps1 que defina la variable $test. En el script, use un modificador de ámbito para hacer referencia a las versiones globales o locales de la variable $test.

En Sample.ps1:

$global:test = "Local"
"The global value of `$test is $global:test."

Una vez completado el script, se cambia el valor global de $test.

PS>  $test
Local

Ejemplo 4: Creación de una variable privada

Una variable privada es una variable que tiene una propiedad Option que tiene un valor de Private. Las variables privadas son heredadas por el ámbito secundario, pero solo se pueden ver o cambiar en el ámbito en el que se crearon.

El siguiente comando crea una variable privada a la que se llama $ptest en el ámbito local.

New-Variable -Name ptest -Value 1 -Option private

Puede mostrar y cambiar el valor de $ptest en el ámbito local.

PS>  $ptest
1

PS>  $ptest = 2
PS>  $ptest
2

A continuación, cree un script Sample.ps1 que contenga los siguientes comandos. El comando intenta mostrar y cambiar el valor de $ptest.

En Sample.ps1:

"The value of `$Ptest is $Ptest."
"The value of `$Ptest is $global:Ptest."

La $ptest variable no está visible en el ámbito del script, la salida está vacía.

"The value of $Ptest is ."
"The value of $Ptest is ."

Ejemplo 5: Uso de una variable local en un comando remoto

Para las variables de un comando remoto creado en la sesión local, use el modificador de ámbito Using. PowerShell supone que las variables de los comandos remotos se crearon en la sesión remota.

La sintaxis es:

$Using:<VariableName>

Por ejemplo, los siguientes comandos crean una variable $Cred en la sesión local y, a continuación, usan la variable $Cred en un comando remoto:

$Cred = Get-Credential
Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $Using:Cred}

El ámbito Using se introdujo en PowerShell 3.0. En PowerShell 2.0, para indicar que se creó una variable en la sesión local, use el siguiente formato de comando.

$Cred = Get-Credential
Invoke-Command $s {
  param($c)
  Remove-Item .\Test*.ps1 -Credential $c
} -ArgumentList $Cred

Consulte también