about_Scopes

適用於: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0, Windows PowerShell 5.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 範圍修飾詞:

       $script:a = "one"

您也可以在函式中使用範圍修飾詞。下列函式定義會在全域範圍中建立函式:

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

您也可以使用範圍修飾詞來表示不同範圍中的變數。下列命令表示 $test 變數,第一個變數是在區域範圍中,而第二個變數是在全域範圍中:

      $test

      $global:test

USING 範圍修飾詞

Using 是特殊範圍修飾詞,可識別遠端命令中的區域變數。預設會假設遠端命令中的變數已在遠端工作階段中定義。

Using 範圍修飾詞是在 Windows PowerShell 3.0 中引進的。

如需詳細資訊,請參閱 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 指令碼) 卻有自己的範圍。

  • 巢狀提示:
    同樣地,巢狀提示也沒有自己的範圍。當您輸入巢狀提示時,巢狀提示會是環境的子集;但您會留在區域範圍中。

    指令碼沒有自己的範圍。如果您正在偵錯指令碼,而且已到達指令碼的中斷點,即進入指令碼範圍。

  • 私用選項:
    別名和變數具有可接受 [私用] 值的 [選項] 屬性。具有 [私用] 選項的項目可於建立所在的範圍中進行檢視和變更,但無法在該範圍外進行檢視或變更。

    例如,如果您在全域範圍中建立具有 [私用] 選項的變數,然後執行指令碼,則指令碼中的 Get-Variable 命令不會顯示私用變數。即使您使用 global 範圍修飾詞,也可能會發生這種情況。

    您可以使用 New-Variable、Set-Variable、New-Alias 和 Set-Alias Cmdlet 的 Option 參數,將 [選項] 屬性設定為 [私用]。

  • 可見度:
    變數或別名的 [可見度] 屬性決定您是否可於建立所在的容器 (例如模組) 外看到項目。[可見度] 是專為容器所設計,類似於專為範圍所設計之 [選項] 屬性的 [私用] 值。

    [可見性] 屬性接受 [公用] 和 [私用] 值。具有私用可見度的項目只能於建立所在的容器中進行檢視和變更。如果是新增或匯入的容器,則無法檢視或變更具有私用可見度的項目。

    由於 [可見度] 是專為容器所設計,因此其在範圍中的運算方式不同。如果您在全域範圍中建立具有私用可見度的項目,則無法檢視或變更任何範圍中的項目。如果您嘗試檢視或變更具有私用可見度的變數值,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:建立私用變數

私用變數是其 [選項] 屬性為 [私用] 的變數。私用變數可由子範圍繼承,但只能於建立所在的範圍中進行檢視或變更。

下列命令會在區域範圍中建立稱為 $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}

Using 範圍是在 Windows PowerShell 3.0 中引進的。

在 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