スコープがPowerShellスクリプトに与える影響
バッチスクリプトでは、環境変数を変更すると、デフォルトで現在のセッションにグローバルな影響があります。 PowerShellでは、スコープがスクリプトの変更を分離するために使用されるため、正反対のことが言えます。ここでは、スコープがPowerShellスクリプトにどのように影響するか、およびその中やその周辺で作業する方法を探ります。.
スコープとは?
PowerShellでは、「スコープ」とはスクリプトまたはコマンドシェルが動作している現在の環境を指します。スコープは、スクリプトや関数によって意図せずに変更されることから環境内の特定のオブジェクトを保護するために使用されます。特に、以下の事項は、別のスコープから実行されたコマンドによる変更から保護されています。
- 変数
- エイリアス
- 関数
- PowerShellドライブ(PSDrive)
スクリプトまたは関数を実行したとき、またはPowerShellの新しいセッションまたはインスタンスを作成したときに、新しいスコープが作成されます。スクリプトと関数を実行することによって作成されたスコープは、それらが作成されたスコープと「親/子」関係を持ちます。特に特別な意味を持ち、名前でアクセスできるスコープがいくつかあります。
- の グローバル scopeは、PowerShellの起動時に作成されるスコープです。これには、PowerShellに組み込まれている変数、エイリアス、関数、およびPSDriveだけでなく、PowerShellプロファイルによって作成されたものも含まれます。.
- の 地元 scopeは、現在のスコープが何であれを指します。 PowerShellを起動すると、グローバルスコープを参照し、スクリプト内ではスクリプトスコープなどになります。.
- の スクリプト スコープはスクリプトが実行されたときに作成されます。この範囲内で動作する唯一のコマンドは、スクリプト内にあるものです。.
- 非公開 スコープを現在のスコープ内で定義して、他のスコープ内のコマンドが他の方法でアクセスできるアイテムを読み取ったり変更したりできないようにすることができます。.
スコープは、特定のコマンドでは番号で参照することもできます。この場合、現在のスコープはゼロとして参照され、その先祖は増加する整数によって参照されます。たとえば、Globalスコープから実行されたスクリプト内では、Scriptスコープは0になり、Globalスコープは1になります。関数など、Scriptスコープ内でさらにネストされたスコープは、Globalスコープを2として参照します。負の数は子スコープを参照するようには働きません - その理由は間もなく明らかになります.
スコープがコマンドに与える影響
前述のように、あるスコープ内で実行されたコマンドは、特に指示がない限り、別のスコープ内のものには影響しません。たとえば、$ MyVarがGlobalスコープに存在し、スクリプトが$ MyVarを別の値に設定するコマンドを実行した場合、$ MyVarのグローバルバージョンは変更されずにそのまま残り、$ MyVarのコピーは新しいスコープでScriptスコープに配置されます。値。 $ MyVarが存在しない場合、スクリプトはデフォルトでScriptスコープ内でそれを作成します - Globalスコープ内ではありません。スコープ間の実際の親子関係について学習するときに覚えておくことが重要です。.
PowerShellのスコープの親子関係は一方向です。コマンドは、現在のスコープ、その親、およびそれより上の任意のスコープを調べ、必要に応じて変更することができます。しかし、彼らは現在の範囲のどの子にも物事を見たり修正したりすることはできません。これは主に、いったん親スコープに移動した後、その子スコープがその目的を果たしたためにすでに破棄されているためです。たとえば、スクリプトが終了した後に、GlobalスコープからScriptスコープ内の変数を表示または変更する必要があるのはなぜですか。スクリプトや関数の変更を完了後も持続させる必要がある場合は多くありますが、スクリプトの実行前または実行後にスクリプトや関数のスコープ内のオブジェクトに変更を加える必要がある場合はそれほど多くありません。 (通常、このようなことはスクリプトまたは関数自体の一部として処理されます。)
もちろん、例外のないルールは何ですか?上記の例外の1つは、Privateスコープです。 Privateスコープ内のオブジェクトは、それらが作成されたスコープ内で実行されるコマンドにのみアクセス可能です。もう1つの重要な例外は、AllScopeプロパティを持つアイテムです。これらは特別な変数とエイリアスで、スコープの変更はすべてのスコープに影響します。次のコマンドは、どの変数とエイリアスにAllScopeプロパティがあるかを示します。
変数の取得Where-Object $ _。オプション-match 'AllScope' Where-Object $ _。オプション-match 'AllScope')
活動中のスコープ
実際にスコープを見てみるために、コマンドラインから変数$ MyVarが「私はグローバル変数です」という文字列に設定されているPowerShellセッションから始めましょう。その後、Scope-Demo.ps1というファイルから次のスクリプトが実行されます。
Function FunctionScope '関数で$ MyVarを変更します。' $ MyVar = '関数によって設定されました!' "MyVarは$ MyVarと言います" "$ MyVarの現在の値を確認しています。 ' 「MyVarは$ MyVarと言います」「$ MyVarをスクリプトで変更する」 $ MyVar = 'スクリプトで設定しました!' "MyVarは$ MyVarと言う" "FunctionScope"スクリプト終了前にMyVarの最終値をチェックする。 "MyVarは$ MyVarを言います" "
PowerShellスクリプトがバッチスクリプトと同じように機能する場合、$ MyVar(またはバッチ構文では%MyVar%)の値が、 '私はグローバル変数です!'から 'スクリプトで設定された!'に変わると予想されます。そして最後に「関数によって設定されました」に。明示的に再度変更されるか、セッションが終了するまで待機します。しかし、ここで実際に何が起こるのかを見てみましょう。特に、FunctionScope関数がその作業を完了し、Scriptから変数を再度チェックした後、Globalスコープをチェックした後です。.
FunctionScope関数が完成するまで、最後に変更されたのと同じスコープ内から変数をチェックしていたため、スクリプトを移動するにつれて変数が変化したように見えます。ただし、FunctionScopeが実行された後は、$ MyVarが関数の影響を受けないままになっているScriptスコープに戻りました。その後、スクリプトが終了したときに、私たちはグローバルスコープに戻りました。.
ローカルスコープの外側に到達する
そのため、スクリプトや機能以外にも誤って環境に変更を加えないようにするのに役立ちますが、実際にそのような変更を加えたい場合はどうしますか。 Localスコープを超えてオブジェクトを作成および変更するための、特殊でかなり単純な構文があります。スコープ名を変数名の先頭に置き、スコープと変数名の間にコロンを入れるだけです。このような:
$ global:MyVar $ script:MyVar $ local:MyVar
変数を表示および設定するときにこれらの修飾子を使用できます。このデモスクリプトで何が起こるか見てみましょう。
Function FunctionScope "ローカル関数スコープで$ MyVarを変更します… '$ local:MyVar ="これは関数のローカルスコープでMyVarです。' 'スクリプトスコープで$ MyVarを変更します…' $ script:MyVar = 'スクリプトで設定し、関数で設定します "グローバルスコープで$ MyVarを変更します… '$ global:MyVar =' MyVarはグローバルスコープで設定されています。 「各スコープで$ MyVarをチェックしています…」「Local:$ local:MyVar」「Script:$ script:MyVar」「Global:$ global:MyVar」「」「$ MyVarの現在の値を取得しています。」 「MyVarは$ MyVarと言います」「$ MyVarをスクリプトで変更する」 $ MyVar = 'スクリプトで設定しました!' "MyVar says $ MyVar" FunctionScope '終了する前にスクリプトスコープから$ MyVarをチェックしています。 "MyVarは$ MyVarを言います" "
前と同様に、グローバルスコープで変数を設定することから始め、最終的なグローバルスコープの結果を確認することで終わります。.
ここでは、FunctionScopeがScriptスコープ内の変数を変更し、変更が完了した後もその変更を保持できることがわかります。また、Globalスコープ内の変数への変更は、スクリプトが終了した後も持続しました。これは、同じコードを使用して、スクリプト内またはGlobalスコープ内で変数を繰り返し変更する必要がある場合に特に役立ちます。変数を変更する場所と方法を変更するために書かれた関数またはスクリプトを定義するだけです。それらの変更が必要なときはいつでもそのことを要求する.
前述のように、スコープ番号を特定のコマンドで使用して、ローカルスコープに対してさまざまなレベルで変数を変更することもできます。上記の2番目の例で使用したものと同じスクリプトですが、名前付きスコープで変数を直接参照するのではなく、スコープ番号を指定してGet-VariableおよびSet-Variableコマンドを使用するように関数を変更しています。
Function FunctionScope "スコープ0内の$ MyVarをFunctionScopeに対して相対的に変更… 'Set-Variable MyVar"これは、関数のスコープ0内のMyVarです。 "スコープ1'内で$ MyVarを変更します、FunctionScope… 'Set-Variable MyVar 'MyVarはスコープ1で関数から変更されました。' -Scope 1 'スコープ2で$ MyVarをFunctionscopeと比較して変更…' Set-Variable MyVar 'MyVarはスコープ2で関数から変更されました。 - スコープ2:各スコープで$ MyVarをチェックする…スコープ0: 'Get-Variable MyVar -Scope 0 -ValueOnly'スコープ1: 'Get-Variable MyVar -Scope 1 -ValueOnly'スコープ2: 'Get-Variable MyVar -Scope 2 -ValueOnly "" $ MyVarの現在の値を取得します。 「MyVarは$ MyVarと言います」「$ MyVarをスクリプトで変更する」 $ MyVar = 'スクリプトで設定しました!' "MyVar says $ MyVar" FunctionScope '終了する前にスクリプトスコープから$ MyVarをチェックしています。 "MyVarは$ MyVarを言います" "
以前と同様に、あるスコープ内のコマンドがその親スコープ内のオブジェクトをどのように変更できるかがわかります。.
追加情報
この記事に収まる以上に、スコープを使ってできることはまだたくさんあります。スコープは単なる変数以上のものに影響を与えますが、PrivateスコープとAllScope変数について学ぶべきことはまだたくさんあります。より有用な情報を得るために、PowerShell内から次のコマンドを実行できます。
get_ヘルプabout_scopes
TechNetでも同じヘルプファイルが利用できます。.
スコープイメージクレジット:openclipartのspadassin