スコープについて
簡単な説明
PowerShell のスコープの概念について説明し、要素のスコープを設定および変更する方法を示します。
長い説明
PowerShell は、変数、エイリアス、関数、PowerShell ドライブ (PSDrive) へのアクセスを、読み取りおよび変更できる場所を制限することで保護します。 PowerShell では、スコープ ルールを使用して、変更すべきではない項目を誤って変更しないようにします。
スコープの基本的な規則を次に示します。
スコープは入れ子になる場合があります。 外部スコープは親スコープと呼ばれます。 入れ子になったスコープは、その親の子スコープです。
アイテムは、明示的にプライベートにしない限り、作成されたスコープと子スコープに表示されます。 変数、エイリアス、関数、または PowerShell ドライブは、1 つ以上のスコープに配置できます。
スコープ内で作成したアイテムは、別のスコープを明示的に指定しない限り、そのアイテムが作成されたスコープ内でのみ変更できます。
スコープ内にアイテムを作成し、そのアイテムが別のスコープ内のアイテムと名前を共有している場合、元のアイテムは新しいアイテムの下で非表示になる可能性がありますが、オーバーライドまたは変更されません。
PowerShell スコープ
PowerShell では、次のスコープがサポートされています。
グローバル: PowerShell の起動時に有効なスコープ。 PowerShell の起動時に存在する変数と関数は、自動変数や基本設定変数など、グローバル スコープで作成されています。 PowerShell プロファイルの変数、エイリアス、関数もグローバル スコープで作成されます。
ローカル: 現在のスコープ。 ローカル スコープには、グローバル スコープまたはその他のスコープを指定できます。
スクリプト: スクリプト ファイルの実行中に作成されるスコープ。 スクリプト内のコマンドのみがスクリプト スコープで実行されます。 スクリプト内のコマンドの場合、スクリプト スコープはローカル スコープです。
注意
プライベート はスコープではありません。 これは、アイテムが定義されているスコープ外のアイテムの表示を変更する オプション です。
親スコープと子スコープ
新しいスコープを作成するには、スクリプトまたは関数を実行するか、セッションを作成するか、PowerShell の新しいインスタンスを開始します。 新しいスコープを作成すると、結果は親スコープ (元のスコープ) と子スコープ (作成したスコープ) になります。
PowerShell では、すべてのスコープはグローバル スコープの子スコープですが、多くのスコープと多くの再帰スコープを作成できます。
アイテムを明示的にプライベートにしない限り、親スコープ内のアイテムは子スコープで使用できます。 ただし、子スコープで作成および変更した項目は、アイテムの作成時にスコープを明示的に指定しない限り、親スコープには影響しません。
継承
子スコープは、親スコープから変数、エイリアス、および関数を継承しません。 アイテムがプライベートでない限り、子スコープは親スコープ内のアイテムを表示できます。 また、親スコープを明示的に指定することで項目を変更できますが、項目は子スコープの一部ではありません。
ただし、子スコープは一連の項目で作成されます。 通常、 AllScope オプションを持つすべてのエイリアスが含まれます。 このオプションについては、この記事の後半で説明します。 AllScope オプションを持つすべての変数と、いくつかの自動変数が含まれます。
特定のスコープ内の項目を検索するには、 または Get-Alias
の Scope パラメーターGet-Variable
を使用します。
たとえば、ローカル スコープ内のすべての変数を取得するには、次のように入力します。
Get-Variable -Scope local
グローバル スコープ内のすべての変数を取得するには、次のように入力します。
Get-Variable -Scope global
スコープ修飾子
変数、エイリアス、または関数名には、次のいずれかの省略可能なスコープ修飾子を含めることができます。
global:
- グローバル スコープに名前が存在することを指定します。local:
- ローカル スコープに名前が存在することを指定します。 現在のスコープは常に ローカル スコープです。private:
- 名前が Private であり、現在のスコープにのみ表示されることを指定します。script:
- スクリプト スコープに名前が存在することを指定します。 スクリプト スコープは、最も近い先祖スクリプト ファイルのスコープです。最も近い先祖スクリプト ファイルがない場合は Global です。using:
- やInvoke-Command
などのStart-Job
コマンドレットを使用してスクリプトを実行しているときに、別のスコープで定義された変数にアクセスするために使用されます。workflow:
- ワークフロー内に名前が存在することを指定します。 注: ワークフローは PowerShell Core ではサポートされていません。<variable-namespace>
- PowerShell PSDrive プロバイダーによって作成された修飾子。 例:名前空間 説明 Alias:
現在のスコープで定義されているエイリアス Env:
現在のスコープで定義されている環境変数 Function:
現在のスコープで定義されている関数 Variable:
現在のスコープで定義されている変数
スクリプトの既定のスコープはスクリプト スコープです。 関数とエイリアスの既定のスコープは、スクリプトで定義されている場合でもローカル スコープです。
スコープ修飾子の使用
新しい変数、エイリアス、または関数のスコープを指定するには、スコープ修飾子を使用します。
変数内のスコープ修飾子の構文は次のとおりです。
$[<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 は、リモート コマンドでローカル変数を識別する特殊なスコープ修飾子です。 修飾子を指定しない場合、PowerShell はリモート コマンドの変数がリモート セッションで定義されることを想定しています。
Using スコープ修飾子は、PowerShell 3.0 で導入されています。
詳細については、「 about_Remote_Variables」を参照してください。
AllScope オプション
変数とエイリアスには、AllScope の値を受け取ることができる Option プロパティがあります。 AllScope プロパティを持つ項目は、作成する子スコープの一部になりますが、親スコープによってさかのぼって継承されることはありません。
AllScope プロパティを持つ項目は子スコープに表示され、そのスコープの一部です。 スコープ内の項目に対する変更は、変数が定義されているすべてのスコープに影響します。
スコープの管理
いくつかのコマンドレットには、特定の スコープ 内の項目を取得または設定 (作成および変更) できる Scope パラメーターがあります。 次のコマンドを使用して、 スコープ パラメーターを持つセッション内のすべてのコマンドレットを検索します。
Get-Help * -Parameter scope
特定のスコープで表示される変数を見つけるには、 の Get-Variable
パラメーターをScope
使用します。 表示される変数には、グローバル変数、親スコープの変数、および現在のスコープ内の変数が含まれます。
たとえば、次のコマンドは、ローカル スコープに表示される変数を取得します。
Get-Variable -Scope local
特定のスコープに変数を作成するには、スコープ修飾子または の Scope パラメーターを使用します Set-Variable
。 次のコマンドは、グローバル スコープに変数を作成します。
New-Variable -Scope global -Name a -Value "One"
、、または Get-Alias
コマンドレットの Scope パラメーターをNew-Alias
Set-Alias
使用して、スコープを指定することもできます。 次のコマンドは、グローバル スコープにエイリアスを作成します。
New-Alias -Scope global -Name np -Value Notepad.exe
特定のスコープ内の関数を取得するには、スコープ内 Get-Item
にいるときに コマンドレットを使用します。 コマンドレットには Get-Item
Scope パラメーターがありません。
注意
Scope パラメーターを使用するコマンドレットについては、 スコープ を数値で参照することもできます。 数値は、あるスコープから別のスコープへの相対位置を表します。 スコープ 0 は、現在またはローカルのスコープを表します。 スコープ 1 は、直接の親スコープを示します。 スコープ 2 は、親スコープの親を示します。などです。 番号付きスコープは、多くの再帰スコープを作成した場合に便利です。
スコープでのドット ソース表記の使用
スクリプトと関数は、スコープのすべてのルールに従います。 特定のスコープで作成し、コマンドレット パラメーターまたはスコープ修飾子を使用してそのスコープを変更しない限り、そのスコープにのみ影響します。
ただし、ドット ソース表記を使用して、スクリプトまたは関数を現在のスコープに追加できます。 次に、スクリプトを現在のスコープで実行すると、スクリプトによって作成される関数、エイリアス、変数が現在のスコープで使用できるようになります。
現在のスコープに関数を追加するには、関数呼び出しで関数のパスと名前の前にドット (.) とスペースを入力します。
たとえば、スクリプト スコープ (スクリプトの既定値) で C:\Scripts ディレクトリから Sample.ps1 スクリプトを実行するには、次のコマンドを使用します。
c:\scripts\sample.ps1
ローカル スコープで Sample.ps1 スクリプトを実行するには、次のコマンドを使用します。
. c:\scripts.sample.ps1
呼び出し演算子 (&) を使用して関数またはスクリプトを実行する場合、現在のスコープには追加されません。 次の例では、呼び出し演算子を使用します。
& c:\scripts.sample.ps1
呼び出し演算子の詳細については、 about_operatorsを参照してください。
Sample.ps1 スクリプトによって作成されるエイリアス、関数、または変数は、現在のスコープでは使用できません。
スコープなしの制限
いくつかの PowerShell の概念は、スコープに似ているか、スコープと対話します。 これらの概念は、スコープまたはスコープの動作と混同される可能性があります。
セッション、モジュール、入れ子になったプロンプトは自己完結型の環境ですが、セッション内のグローバル スコープの子スコープではありません。
セッション
セッションは、PowerShell を実行する環境です。 リモート コンピューターでセッションを作成すると、PowerShell によってリモート コンピューターへの永続的な接続が確立されます。 永続的な接続を使用すると、複数の関連コマンドにセッションを使用できます。
セッションは包含環境であるため、独自のスコープを持ちますが、セッションは作成されたセッションの子スコープではありません。 セッションは、独自のグローバル スコープで開始されます。 このスコープは、セッションのグローバル スコープとは無関係です。 セッションで子スコープを作成できます。 たとえば、スクリプトを実行して、セッションに子スコープを作成できます。
モジュール
PowerShell モジュールを使用して、PowerShell ツールを共有および配信できます。 モジュールは、コマンドレット、スクリプト、関数、変数、エイリアス、およびその他の便利な項目を含むことができるユニットです。 明示的に定義されていない限り、モジュール内の項目にはモジュールの外部からアクセスできません。 そのため、セッションにモジュールを追加し、他の項目がセッション内のコマンドレット、スクリプト、関数、およびその他の項目をオーバーライドする可能性があることを心配することなく、パブリック項目を使用できます。
モジュールのプライバシーはスコープのように動作しますが、モジュールをセッションに追加してもスコープは変更されません。 また、モジュールには独自のスコープはありませんが、モジュール内のスクリプトは、すべての PowerShell スクリプトと同様に、独自のスコープを持ちます。
既定では、モジュールは現在のスコープではなく、現在のセッション状態の最上位レベルに読み込まれます。 これは、モジュール セッション状態またはグローバル セッション状態である可能性があります。 グローバル スコープの場合、モジュールはグローバル セッション状態に読み込まれます。 エクスポートはすべてグローバル テーブルに配置されます。
module2 を module1 内 から読み込む場合、module2 はグローバル セッション状態ではなく module1 のセッション状態に読み込まれます。 module2 からのエクスポートはすべて、module1 のセッション状態の先頭に配置されます。 を使用 Import-Module -Scope local
すると、エクスポートは最上位ではなく現在のスコープ オブジェクトに配置されます。 モジュール内で (またはImport-Module -Global
) を使用Import-Module -Scope global
して別のモジュールを読み込む場合、そのモジュールとそのエクスポートは、モジュールのローカル セッション状態ではなくグローバル セッション状態に読み込まれます。 この機能は、モジュールを操作するモジュールを記述するために設計されています。 WindowsCompatibility モジュールは、プロキシ モジュールをグローバル スコープにインポートするためにこれを行います。
入れ子になったプロンプト
同様に、入れ子になったプロンプトには独自のスコープがありません。 入れ子になったプロンプトを入力すると、入れ子になったプロンプトは環境のサブセットになります。 ただし、ローカル スコープ内に残ります。
スクリプトには独自のスコープがあります。 スクリプトをデバッグしていて、スクリプトのブレークポイントに到達した場合は、スクリプト スコープを入力します。
プライベート オプション
エイリアスと変数には、Private の値を受け取ることができる Option プロパティがあります。 [プライベート] オプションを持つアイテムは、作成されたスコープで表示および変更できますが、そのスコープ外で表示または変更することはできません。
たとえば、グローバル スコープでプライベート オプションを持つ変数を作成し、スクリプトを実行した場合、 Get-Variable
スクリプト内のコマンドにはプライベート変数は表示されません。 このインスタンスでグローバル スコープ修飾子を使用しても、プライベート変数は表示されません。
、、、および Set-Alias
コマンドレットの Option パラメーターをSet-Variable
New-Variable
New-Alias
使用して、Option プロパティの値を Private に設定できます。
可視性
変数またはエイリアスの Visibility プロパティは、コンテナーの外部にアイテムが作成されたアイテムを表示できるかどうかを決定します。 コンテナーには、モジュール、スクリプト、またはスナップインを指定できます。 可視性は、Option プロパティの Private 値がスコープ用に設計されているのと同じ方法でコンテナー用に設計されています。
Visibility プロパティは、Public 値と Private 値を受け取ります。 プライベート可視性を持つ項目は、作成されたコンテナーでのみ表示および変更できます。 コンテナーが追加またはインポートされた場合、プライベート可視性を持つ項目を表示または変更することはできません。
可視性はコンテナー用に設計されているため、スコープ内では動作が異なります。
- グローバル スコープでプライベート可視性を持つアイテムを作成した場合、どのスコープでもアイテムを表示または変更することはできません。
- プライベート可視性を持つ変数の値を表示または変更しようとすると、PowerShell からエラー メッセージが返されます。
コマンドレットと Set-Variable
コマンドレットをNew-Variable
使用して、プライベート可視性を持つ変数を作成できます。
例
例 1: スクリプト内の変数値のみを変更する
次のコマンドは、スクリプト内の変数の $ConfirmPreference
値を変更します。 この変更はグローバル スコープには影響しません。
最初に、ローカル スコープで変数の値を $ConfirmPreference
表示するには、次のコマンドを使用します。
PS> $ConfirmPreference
High
次のコマンドを含む Scope.ps1 スクリプトをCreateします。
$ConfirmPreference = "Low"
"The value of `$ConfirmPreference is $ConfirmPreference."
スクリプトを実行します。 スクリプトは変数の値を $ConfirmPreference
変更し、その値をスクリプト スコープで報告します。 出力は次の出力のようになります。
The value of $ConfirmPreference is Low.
次に、現在のスコープ内の変数の $ConfirmPreference
現在の値をテストします。
PS> $ConfirmPreference
High
この例は、スクリプト スコープ内の変数の値に対する変更が、親スコープ内の変数の値に影響しないことを示しています。
例 2: 異なるスコープの変数値を表示する
スコープ修飾子を使用して、ローカル スコープと親スコープ内の変数の値を表示できます。
最初に $test
、グローバル スコープで変数を定義します。
$test = "Global"
次に、変数を定義する Sample.ps1 スクリプトを作成します $test
。 スクリプトで、スコープ修飾子を使用して、変数のグローバル バージョンまたはローカル バージョンを参照します $test
。
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
のみがセッションで定義されます。
PS> $test
Global
例 3: 親スコープ内の変数の値を変更する
Private オプションまたは別のメソッドを使用して項目を保護しない限り、親スコープ内の変数の値を表示および変更できます。
最初に $test
、グローバル スコープで変数を定義します。
$test = "Global"
次に、変数を定義する Sample.ps1 スクリプトを作成します $test
。 スクリプトで、スコープ修飾子を使用して、変数のグローバル バージョンまたはローカル バージョンを参照します $test
。
Sample.ps1:
$global:test = "Local"
"The global value of `$test is $global:test."
スクリプトが完了すると、 のグローバル値 $test
が変更されます。
PS> $test
Local
例 4: プライベート変数の作成
プライベート変数は、値が Private の Option プロパティを持つ変数です。 プライベート 変数は子スコープによって継承されますが、表示または変更できるのは、作成されたスコープのみです。
次のコマンドは、ローカル スコープで というプライベート $ptest
変数を作成します。
New-Variable -Name ptest -Value 1 -Option private
の値 $ptest
は、ローカル スコープで表示および変更できます。
PS> $ptest
1
PS> $ptest = 2
PS> $ptest
2
次に、次のコマンドを含む Sample.ps1 スクリプトを作成します。 コマンドは、 の値 $ptest
の表示と変更を試みます。
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: リモート コマンドでローカル変数を使用する
ローカル セッションで作成されたリモート コマンドの変数の場合は、 scope 修飾子を使用します Using
。 PowerShell では、リモート コマンドの変数がリモート セッションで作成されたものと見なされます。
の構文は次のとおりです。
$Using:<VariableName>
たとえば、次のコマンドは、ローカル セッションで変数を作成 $Cred
し、リモート コマンドで 変数を $Cred
使用します。
$Cred = Get-Credential
Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $Using:Cred}
Using スコープは PowerShell 3.0 で導入されました。 PowerShell 2.0 では、ローカル セッションで変数が作成されたことを示すには、次のコマンド形式を使用します。
$Cred = Get-Credential
Invoke-Command $s {
param($c)
Remove-Item .\Test*.ps1 -Credential $c
} -ArgumentList $Cred