about_Scopes

应用到: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0

主题

about_Scopes

简短说明

说明 Windows PowerShell® 中作用域的概念,并演示如何设置和更改元素的作用域。

详细说明

Windows PowerShell 可保护对变量、别名、函数和 Windows PowerShell 驱动器 (PSDrives) 的访问权限,方法是限制可以读取和更改它们的位置。通过对作用域强制执行一些简单的规则,Windows PowerShell 有助于确保你不会无意中更改不应更改的项目。

以下是作用域的基本规则:

  • - 你包含在作用域中的项在创建它的作用域中以及任何子域中可见,除非你显式使其成为私有项。你可以将变量、别名、函数或 Windows PowerShell 驱动器放置在一个或多个作用域中。

  • - 你在作用域内创建的项只能在创建它的作用域中更改,除非你显式指定不同的作用域。

如果你在作用域中创建某个项,并且该项与其他作用域中的项同名,则原始项可能隐藏在新项下。但是,它并没有覆盖或更改。

WINDOWS POWERSHELL 作用域

Windows PowerShell 中的作用域具有名称和数字。已命名的作用域指定绝对作用域。数字是相对的,并且会反映作用域之间的关系。

  • 全局:
    在 Windows PowerShell 启动时生效的作用域。在 Windows PowerShell 启动时存在的变量和函数已在全局作用域中创建。这包括自动变量和首选项变量。这还包括 Windows PowerShell 配置文件中的变量、别名和函数。
  • 本地:
    当前作用域。本地作用域可以是全局作用域或任何其他作用域。
  • 脚本:
    在脚本文件运行时创建的作用域。仅脚本中的命令在脚本作用域中运行。对于脚本中的命令来说,脚本作用域是本地作用域。
  • 私有:
    无法在当前作用域之外看到私有作用域中的项。你可以使用私有作用域在其他作用域中创建一个私有版本的同名项。
  • 带编号的作用域:
    你可以按名称或按描述一个作用域相对于另一个作用域的相对位置的编号来引用作用域。作用域 0 表示当前(或本地)作用域。作用域 1 指示直接父作用域。作用域 2 指示父作用域的父项,依此类推。如果你已创建了许多递归作用域,则带编号的作用域非常有用。

父作用域和子作用域

你可以通过运行脚本或函数、创建会话或启动 Windows PowerShell 的新实例来创建新作用域。当你创建新作用域时,结果会产生一个父作用域(原始作用域)和一个子作用域(你创建的作用域)。

在 Windows PowerShell 中,所有作用域都是全局作用域的子作用域,但是你可以创建许多作用域和许多递归作用域。

除非你显式使这些项成为私有项,否则父作用域中的项对子作用域可用。但是,你在子作用域中创建和更改的项不会影响父作用域,除非你在创建这些项时显式指定作用域。

继承

子作用域不会从父作用域继承变量、别名和函数。除非某个项是私有项,否则子作用域可以查看父作用域中的项。并且,它可以通过显式指定父作用域来更改这些项,但是这些项不是子作用域的一部分。

但是,使用一组项创建子作用域。通常情况下,它包含具有 AllScope 选项的所有别名。本主题的后面部分将讨论此选项。它包含具有 AllScope 选项的所有变量以及可用于自定义作用域的一些变量,例如 MaximumFunctionCount。

若要查找特定作用域中的项,请使用 Get-Variable 或 Get-Alias 的 Scope 参数。

例如,若要获取本地作用域中的所有变量,请键入:

        get-variable -scope local

若要在全局作用域中获取所有变量,请键入:

        get-variable -scope global

作用域修饰符

若要指定新变量、别名或函数的作用域,请使用作用域修饰符。修饰符的有效值为 Global、Local、Private 和 Script。

变量中的作用域修饰符的语法是:

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

函数中的作用域修饰符的语法是:

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

脚本的默认作用域是脚本作用域。函数和别名的默认作用域是本地作用域,即使在脚本中定义了它们。

以下命令(不使用作用域修饰符)在当前或本地作用域中创建变量:

       $a = "one"

若要在全局作用域中创建相同变量,请使用 Global 作用域修饰符:

       $global:a = "one"

若要在脚本作用域中创建相同变量,请使用脚本作用域修饰符:

       $script:a = "one"

你还可以在函数中使用作用域修饰符。以下函数定义在全局作用域中创建函数:

       function global:Hello
       {
    write-host "Hello, World"
       }

你还可以使用作用域修饰符在不同的作用域中引用变量。以下命令依次在本地作用域中和全局作用域中引用 $test 变量:

      $test

      $global:test

USING 作用域修饰符

Using 是一个在远程命令中标识本地变量的特殊作用域修饰符。默认情况下,假设远程命令中的变量在远程会话中定义。

Windows PowerShell 3.0 中引入了 Using 作用域修饰符。

有关详细信息,请参阅 about_Remote_Variables。

ALLSCOPE 选项

变量和别名具有采用的值为 AllScope 的 Option 属性。具有 AllScope 属性的项成为你创建的任何子作用域的一部分,尽管父作用域不会追溯继承它们。

具有 Allscope 属性的项在子作用域中可见,并且是该作用域的一部分。对任何作用域中的项的更改会影响定义了该变量的所有作用域。

管理作用域

多个 cmdlet 具有的 Scope 参数可使你获取或设置(创建和更改)特定作用域中的项。使用以下命令在你的会话中查找具有 Scope 参数的所有 cmdlet:

         get-help * -parameter scope

若要查找在特定作用域中可见的变量,请使用 Get-Variable 的 Scope 参数。可见参数包括全局参数、父作用域中的参数以及当前作用域中的参数。在此处插入部分正文。

例如,以下命令获取在本地作用域中可见的变量:

        get-variable -scope local

若要在特定作用域中创建变量,请使用作用域修饰符或 Set-Variable 的 Scope 参数。以下命令在全局作用域中创建变量:

        new-variable -scope global -name a -value "One"

你还可以使用 New-Alias、Set-Alias 或 Get-Alias cmdlet 的 Scope 参数指定作用域。以下命令在全局作用域中创建别名:

        new-alias -scope global -name np -value Notepad.exe

若要获取特定作用域中的函数,请在你位于该作用域中时使用 Get-Item cmdlet。Get-Item cmdlet 不具有 scope 参数。

将点源表示法与作用域结合使用

脚本和函数遵循作用域的所有规则。你将在特定作用域中创建它们,它们仅影响该作用域,除非你使用 cmdlet 参数或作用域修饰符来更改该作用域。

但是,你可以使用点源表示法向当前作用域添加脚本或函数。然后,当脚本在当前作用域中运行时,该脚本创建的任何函数、别名和变量在当前作用域中可用。

若要将某个函数添加到当前作用域,请在函数调用中函数的路径和名称前键入一个点 (.) 和一个空格。

例如,若要从脚本作用域中的 C:\Scripts 目录(脚本的默认值)运行 Sample.ps1 脚本,请使用以下命令:

        c:\scripts\sample.ps1

若要在本地作用域中运行 Sample.ps1 脚本,请使用以下命令:

        . c:\scripts.sample.ps1

当你使用调用运算符 (&) 运行函数或脚本时,它不会添加到当前作用域。以下示例使用调用运算符:

        & c:\scripts.sample.ps1

Sample.ps1 脚本创建的任何别名、函数或变量在当前作用域中不可用。

不使用作用域进行限制

一些 Windows PowerShell 概念类似于作用域或与作用域交互。这些概念可能与作用域或作用域的行为混淆。

会话、模块和嵌套提示是自包含的环境,但它们不是会话中的全局作用域的子作用域。

  • 会话:
    会话是在其中运行 Windows PowerShell 的环境。当你在远程计算机上创建会话时,Windows PowerShell 将建立与远程计算机的持久连接。持久连接允许你将该会话用于多个相关命令。

    由于会话是一个包含的环境,因此它有其自己的作用域,但是会话不是创建它的会话的子作用域。会话从其自己的全局作用域开始。此作用域独立于会话的全局作用域。你可以在会话中创建子作用域。例如,你可以运行脚本以在会话中创建子作用域。

  • 模块:
    你可以使用 Windows PowerShell 模块来共享和交付 Windows PowerShell 工具。模块是可包含 cmdlet、脚本、函数、变量、别名和其他有用的项的单元。除非明确定义,否则无法从模块外访问模块中的项。因此,你可以将模块添加到你的会话,并使用公共项,而无需担心其他项可能会在你的会话中覆盖 cmdlet、脚本、函数和其他项。

    私有模块的行为类似于作用域,但是将模块添加到会话不会更改该作用域。而且,模块没有其自己的作用域,尽管模块中的脚本(如所有 Windows PowerShell 脚本)具有其自己的作用域。

  • 嵌套提示:
    同样,嵌套提示没有其自己的作用域。当输入嵌套提示时,嵌套提示是环境的子集。但是,你保留在本地作用域中。

    脚本具有其自己的作用域。如果你正在调试脚本,并且到达了脚本中的断点,则你进入了脚本作用域。

  • 私有选项:
    别名和变量具有采用的值为 Private 的 Option 属性。对于具有私有选项的项,可以在创建它们的作用域中进行查看和更改,但无法在该作用域外进行查看或更改。

    例如,如果你在全局作用域中创建一个具有私有选项的变量,然后运行脚本,该脚本中的 Get-Variable 命令不会显示私有变量。即使你使用全局作用域修饰符,仍然会发生这种情况。

    你可以使用 New-Variable、Set-Variable、New-Alias 和 Set-Alias cmdlet 的 Option 参数来将 Option 属性设置为 Private。

  • 可见性:
    变量或别名的 Visibility 属性确定你是否可以在创建它的容器(例如模块)外看到该项。Visibility 旨在用于容器,如同 Option 属性的 Private 值旨在用于作用域一样。

    Visibility 属性采用 Public 和 Private 值。具有私有可用性的项只能在创建它们的容器中进行查看和更改。如果添加或导入容器,则无法查看或更改具有私有可见性的项。

    由于 Visibility 旨在用于容器,因此它在作用域中的工作原理不同。如果你在全局作用域中创建具有私有可见性的项,则你无法在任何作用域中查看或更改该项。如果你尝试查看或更改具有私有可见性的变量的值,则 Windows PowerShell 将返回一条错误消息。

    你可以使用 New-Variable 和 Set-Variable cmdlet 创建具有私有可见性的变量。

示例

示例 1:仅在脚本中更改变量值

以下命令在脚本中更改 $ConfirmPreference 变量的值。此更改不会影响全局作用域。

首先,若要在本地作用域中显示 $ConfirmPreference 变量的值,请使用以下命令:

          C:\PS> $ConfirmPreference
          High

创建包含以下命令的 Scope.ps1 脚本:

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

运行该脚本。该脚本更改 $ConfirmPreference 变量的值,然后在脚本作用域中报告其值。输出应类似于以下输出:

          The value of $ConfirmPreference is Low.

接下来,在当前作用域中测试 $ConfirmPreference 变量的当前值。

          C:\PS> $ConfirmPreference
          High

此示例演示对脚本作用域中的变量值的更改不会影响父作用域中该变量的值。

示例 2:查看不同作用域中的变量值

你可以使用作用域修饰符查看本地作用域和父作用域中的变量值。

首先,在全局作用域中定义 $test 变量。

        $test = "Global"

接下来,创建定义 $test 变量的 Sample.ps1 脚本。在脚本中,使用作用域修饰符引用 $test 变量的全局或本地版本。在此处插入部分正文。

          # In Sample.ps1

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

当你运行 Sample.ps1 时,输出应与以下输出类似:

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

当脚本完成时,仅在会话中定义 $test 的全局值。

          C:\PS> $test
          Global

示例 3:更改父作用域中的变量的值

除非你使用私有选项或其他方法保护某个项,否则你可以在父作用域中查看和更改变量的值。

首先,在全局作用域中定义 $test 变量。

        $test = "Global"

接下来,创建定义 $test 变量的 Sample.ps1 脚本。在脚本中,使用作用域修饰符引用 $test 变量的全局或本地版本。

          # In Sample.ps1

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

当脚本完成时,更改 $test 的全局值。

          C:\PS> $test
          Local

示例 4:创建私有变量

私有变量是具有值为 Private 的 Option 属性的变量。私有变量由子作用域继承,但只能在创建它们的作用域中查看或更改它们。

以下命令在本地作用域中创建名为 $ptest 的私有变量。

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

你可以在本地作用域中显示和更改 $ptest 的值。

          C:\PS> $ptest
          1
          C:\PS> $ptest = 2
          C:\PS> $ptest
          2

接下来,创建包含以下命令的 Sample.ps1 脚本。该命令尝试显示和更改 $ptest 的值。

          # In Sample.ps1

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

由于 $ptest 变量在脚本作用域中不可见,因此输出为空。

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

示例 5:在远程命令中使用本地变量

若要指示远程命令中的变量已在本地会话中创建,请使用 Using 作用域修饰符。默认情况下,Windows PowerShell 假定远程命令中的变量已在远程会话中创建。

语法是:

           $Using:<VariableName>

例如,以下命令在本地会话中创建 $Cred 变量,然后在远程命令中使用 $Cred 变量:

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

Windows PowerShell 3.0 中引入了 Using 作用域。

在 Windows PowerShell 2.0 中,若要指示某个变量已在本地会话中创建,请使用以下命令格式。

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

另请参阅

about_Variables

about_Environment_Variables

about_Functions

about_Script_Blocks