about_Scopes

簡単な説明

PowerShell のスコープの概念と、要素のスコープを設定および変更する方法について説明します。

長い説明

PowerShell は、変数、エイリアス、関数、PowerShell ドライブ (PSDrive) へのアクセスを保護します。読み取りと変更が可能な場所を制限します。 PowerShell では、スコープ ルールを使用して、変更すべきでない項目を誤って変更しないようにします。

スコープの基本的な規則を次に示します。

  • スコープは入れ子になる可能性があります。 外側のスコープは親スコープと呼ばれます。 入れ子になったスコープは、その親の子スコープです。

  • アイテムは、明示的にプライベートにしない限り、作成されたスコープと子スコープに表示されます。

  • 現在のスコープ外のスコープに対して、変数、エイリアス、関数、PowerShell ドライブを宣言できます。

  • スコープ内で作成した項目は、別のスコープを明示的に指定しない限り、作成されたスコープ内でのみ変更できます。

スコープ内にアイテムを作成し、そのアイテムが別のスコープ内のアイテムと名前を共有している場合、元のアイテムは新しいアイテムの下に非表示になる可能性がありますが、オーバーライドまたは変更されません。

PowerShell スコープ

PowerShell では、次のスコープがサポートされています。

  • グローバル: PowerShell の起動時、または新しいセッションまたは実行空間を作成するときに有効になるスコープ。 PowerShell の起動時に存在する変数と関数は、自動変数や基本設定変数など、グローバル スコープで作成されています。 PowerShell プロファイルの変数、エイリアス、関数もグローバル スコープで作成されます。 グローバル スコープは、セッションのルート親スコープです。

  • ローカル: 現在のスコープ。 ローカル スコープには、グローバル スコープまたはその他のスコープを指定できます。

  • スクリプト: スクリプト ファイルの実行中に作成されるスコープ。 スクリプト スコープで実行されるのは、スクリプト内のコマンドだけです。 スクリプト内のコマンドの場合、スクリプト スコープはローカル スコープです。

親スコープと子スコープ

スクリプトまたは関数を呼び出すことで、新しい子スコープを作成できます。 呼び出し元のスコープは親スコープです。 呼び出されたスクリプトまたは関数が子スコープです。 呼び出す関数またはスクリプトは他の関数を呼び出すことがあり、ルート スコープがグローバル スコープである子スコープの階層が作成されます。

明示的にアイテムをプライベートにしない限り、親スコープ内のアイテムは子スコープで使用できます。 ただし、子スコープで作成および変更した項目は、項目の作成時にスコープを明示的に指定しない限り、親スコープには影響しません。

注意

モジュールの関数は、呼び出し元スコープの子スコープでは実行されません。 モジュールには、グローバル スコープにリンクされている独自のセッション状態があります。 すべてのモジュール コードは、独自のルート スコープを持つスコープのモジュール固有の階層で実行されます。

継承

子スコープは、親スコープから変数、エイリアス、および関数を継承しません。 アイテムがプライベートでない限り、子スコープは親スコープ内のアイテムを表示できます。 また、親スコープを明示的に指定することで項目を変更できますが、項目は子スコープの一部ではありません。

ただし、子スコープは一連の項目で作成されます。 通常、 AllScope オプションを持つすべてのエイリアスが含まれます。 このオプションについては、この記事の後半で説明します。 AllScope オプションを持つすべての変数と、いくつかの自動変数が含まれます。

特定のスコープ内の項目を検索するには、Scope パラメーター Get-Variable または Get-Alias.

たとえば、ローカル スコープ内のすべての変数を取得するには、次のように入力します。

Get-Variable -Scope local

グローバル スコープ内のすべての変数を取得するには、次のように入力します。

Get-Variable -Scope global

スコープ修飾子

変数、エイリアス、または関数名には、次のいずれかの省略可能なスコープ修飾子を含めることができます。

  • global: - グローバル スコープに名前が存在することを指定します。

  • local: - 名前がローカル スコープに存在することを指定します。 現在のスコープは常に ローカル スコープです。

  • private: - 名前が Private であり、現在のスコープにのみ表示されることを指定します。

    注意

    private はスコープではありません。 これは、項目が定義されているスコープ外の項目の可視性を変更する オプション です。

  • script: - スクリプト スコープに名前が存在することを指定します。 スクリプト スコープは、最も近い先祖スクリプト ファイルのスコープです。最も近い先祖スクリプト ファイルがない場合は グローバル です。

  • using: - コマンドレットを Start-Job 使用してスクリプトを実行しているときに、別のスコープで定義された変数にアクセスするために使用されます Invoke-Command

  • workflow: - ワークフロー内に名前が存在することを指定します。 注: ワークフローは、PowerShell v6 以降ではサポートされていません。

  • <variable-namespace> - PowerShell PSDrive プロバイダーによって作成された修飾子。 次に例を示します。

    名前空間 説明
    Alias: 現在のスコープで定義されているエイリアス
    Env: 現在のスコープで定義されている環境変数
    Function: 現在のスコープで定義されている関数
    Variable: 現在のスコープで定義されている変数

スクリプトの既定のスコープはスクリプト スコープです。 関数とエイリアスの既定のスコープは、スクリプトで定義されている場合でもローカル スコープです。

スコープ修飾子の使用

新しい変数、エイリアス、または関数のスコープを指定するには、スコープ修飾子を使用します。

変数内のスコープ修飾子の構文は次のとおりです。

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

関数内のスコープ修飾子の構文は次のとおりです。

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

スコープ修飾子を使用しない次のコマンドは、現在のスコープまたは ローカル スコープに変数を作成します。

$a = "one"

グローバル スコープで同じ変数を作成するには、スコープglobal:修飾子を使用します。

$global:a = "one"
Get-Variable a | Format-List *

Visibility プロパティと Options プロパティの値に注目してください。

Name        : a
Description :
Value       : one
Visibility  : Public
Module      :
ModuleName  :
Options     : None
Attributes  : {}

これをプライベート変数と比較します。

$private:pVar = 'Private variable'
Get-Variable pVar | Format-List *

スコープ修飾子を private 使用すると 、Options プロパティ Privateが .

Name        : pVar
Description :
Value       : Private variable
Visibility  : Public
Module      :
ModuleName  :
Options     : Private
Attributes  : {}

スクリプト スコープに同じ変数を作成するには、スコープ修飾子をscript:使用します。

$script:a = "one"

スコープ修飾子を関数と共に使用することもできます。 次の関数定義は、 グローバル スコープに関数を作成します。

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

また、スコープ修飾子を使用して、別のスコープ内の変数を参照することもできます。 次のコマンドは、最初に $test ローカル スコープで、次にグローバル スコープで変数を参照します。

$test
$global:test

Using:スコープ修飾子

Using は、リモート コマンドでローカル変数を識別する特殊なスコープ修飾子です。 修飾子がない場合、PowerShell はリモート コマンドの変数をリモート セッションで定義することを想定しています。

Usingスコープ修飾子は PowerShell 3.0 で導入されています。

セッション外で実行されるスクリプトまたはコマンドの場合は、呼び出し元の Using セッション スコープから変数値を埋め込むためのスコープ修飾子が必要です。そのため、セッション外のコードからそれらにアクセスできます。 Usingスコープ修飾子は、次のコンテキストでサポートされています。

  • ComputerName パラメーターまたは Session パラメーターを使用して開始Invoke-Commandされたリモートで実行されたコマンド (リモート セッション)
  • バックグラウンド ジョブ(プロセス外セッション) で Start-Job 開始
  • スレッド ジョブ(別のスレッド セッションを介して Start-ThreadJob 開始)または ForEach-Object -Parallel (個別のスレッド セッション)

コンテキストに応じて、埋め込み変数の値は、呼び出し元のスコープ内のデータの独立したコピーであるか、それに対する参照です。 リモート セッションとアウトプロセス セッションでは、常に独立したコピーです。

詳細については、「 about_Remote_Variables」を参照してください。

スレッド セッションでは、参照渡しされます。 つまり、別のスレッドで呼び出しスコープ変数を変更できます。 変数を安全に変更するには、スレッド同期が必要です。

詳細については、次のトピックを参照してください。

変数値のシリアル化

リモートで実行されたコマンドとバックグラウンド ジョブは、アウトプロセスで実行されます。 アウトプロセス セッションでは、XML ベースのシリアル化と逆シリアル化を使用して、プロセス境界を越えて変数の値を使用できるようにします。 シリアル化プロセスは、元のオブジェクト プロパティを含むが、そのメソッドを含まない PSObject にオブジェクトを変換します。

型のセットが限られている場合、逆シリアル化によってオブジェクトが元の型に戻されます。 リハイドレートされたオブジェクトは、元のオブジェクト インスタンスのコピーです。 型のプロパティとメソッドがあります。 System.Version などの単純な型の場合、コピーは正確です。 複合型の場合、コピーは不完全です。 たとえば、リハイドレートされた証明書オブジェクトには秘密キーは含まれません。

他のすべての型のインスタンスは PSObject インスタンスです。 PSTypeNames プロパティには、逆シリアル化された元の型名 (Deserialized.System.Data.DataTable など) が含まれています

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"

またはコマンドレットの Scope パラメーターをNew-AliasSet-AliasGet-Alias使用して、スコープを指定することもできます。 次のコマンドは、グローバル スコープにエイリアスを作成します。

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

特定のスコープ内の関数を取得するには、スコープ内 Get-Item にあるときにコマンドレットを使用します。 コマンドレットには Get-ItemScope パラメーターがありません。

注意

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 ツールを共有および配信できます。 モジュールは、コマンドレット、スクリプト、関数、変数、エイリアス、およびその他の便利な項目を含めることができるユニットです。 明示的に定義されていない限り、モジュール内の項目はモジュールの外部からはアクセスできません。 したがって、セッションにモジュールを追加し、他の項目がコマンドレット、スクリプト、関数、およびセッション内の他の項目をオーバーライドする可能性があることを心配することなく、パブリック項目を使用できます。

既定では、モジュールは現在のスコープではなく、現在のセッション状態の最上位レベルに読み込まれます。 現在のセッション状態は、モジュール セッション状態またはグローバル セッション状態である可能性があります。 モジュールをセッションに追加しても、スコープは変更されません。 グローバル スコープ内の場合、モジュールはグローバル セッション状態に読み込まれます。 エクスポートはすべてグローバル テーブルに配置されます。 module1 から module2 を読み込む場合、module2 はグローバル セッション状態ではなく module1 のセッション状態に読み込まれます。 module2 からのエクスポートはすべて、module1 セッション状態の先頭に配置されます。 使用 Import-Module -Scope localする場合、エクスポートは最上位ではなく現在のスコープ オブジェクトに配置されます。 モジュール内で別のモジュールImport-Module -Scope global を読み込む (またはImport-Module -Global) 場合、そのモジュールとそのエクスポートは、モジュールのローカル セッション状態ではなくグローバル セッション状態に読み込まれます。 この機能は、モジュールを操作するモジュールを記述するために設計されています。 WindowsCompatibility モジュールは、プロキシ モジュールをグローバル セッション状態にインポートするためにこれを行います。

セッション状態内では、モジュールには独自のスコープがあります。 次のモジュール C:\temp\mod1.psm1を検討してください。

$a = "Hello"

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

次に、グローバル変数 $aを作成し、値を指定して関数 foo を呼び出 します

$a = "Goodbye"
foo

モジュールはモジュールスコープで変数 $a を宣言し、関数 foo は両方のスコープで変数の値を出力します。

$a = Hello
$global:a = Goodbye

入れ子になったプロンプト

入れ子になったプロンプトには、独自のスコープがありません。 入れ子になったプロンプトを入力すると、入れ子になったプロンプトは環境のサブセットになります。 ただし、ローカル スコープ内に残ります。

スクリプトには独自のスコープがあります。 スクリプトをデバッグしていて、スクリプトのブレークポイントに到達した場合は、スクリプト スコープを入力します。

プライベート オプション

エイリアスと変数には、Privateを受け取ることができる Option プロパティがあります。 オプションを Private 持つ項目は、作成されるスコープで表示および変更できますが、そのスコープ外で表示または変更することはできません。

たとえば、グローバル スコープでプライベート オプションを持つ変数を作成し、スクリプトを実行すると、 Get-Variable スクリプト内のコマンドにプライベート変数は表示されません。 このインスタンスでグローバル スコープ修飾子を使用しても、プライベート変数は表示されません。

、、New-AliasおよびSet-Aliasコマンドレットの Option パラメーターをNew-VariableSet-Variable使用して、Option プロパティの値を Private に設定できます。

表示

変数またはエイリアスの Visibility プロパティは、コンテナーの外部 (作成された項目) を表示できるかどうかを決定します。 コンテナーには、モジュール、スクリプト、スナップインを指定できます。 可視性は、Option プロパティの値がスコープ用にPrivate設計されているのと同じ方法でコンテナー用に設計されています。

Visibility プロパティは、値とPrivate値をPublic受け取ります。 プライベート可視性を持つ項目は、作成されたコンテナーでのみ表示および変更できます。 コンテナーが追加またはインポートされた場合、プライベート可視性を持つ項目を表示または変更することはできません。

可視性はコンテナー用に設計されているため、スコープ内では動作が異なります。

  • グローバル スコープで非公開の可視性を持つアイテムを作成した場合、どのスコープでもアイテムを表示または変更することはできません。
  • プライベート可視性を持つ変数の値を表示または変更しようとすると、PowerShell からエラー メッセージが返されます。

コマンドレットとSet-VariableコマンドレットをNew-Variable使用して、プライベート可視性を持つ変数を作成できます。

例 1: スクリプト内でのみ変数値を変更する

次のコマンドは、スクリプト内の変数の $ConfirmPreference 値を変更します。 この変更は、グローバル スコープには影響しません。

最初に、ローカル スコープ内の変数の値を $ConfirmPreference 表示するには、次のコマンドを使用します。

PS>  $ConfirmPreference
High

次のコマンドを含むScope.ps1 スクリプトを作成します。

$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: プライベート変数の作成

プライベート変数は、値が 〗の Option プロパティを持つ変数です PrivatePrivate 変数は子スコープによって継承されますが、表示または変更できるのは、変数が作成されたスコープ内のみです。

次のコマンドは、ローカル スコープで呼び出される $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: リモート コマンドでローカル変数を使用する

ローカル セッションで作成されたリモート コマンドの変数には、スコープ修飾子を 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

こちらもご覧ください