Scopes
A scope is a logical
boundary in PowerShell that isolates the use of functions and
variables. Scopes can be defined as global, local, script, and private.
They function in a hierarchy in which scope information is inherited
downward. For example, the local scope can read the global scope, but
the global scope can’t read information from the local scope. Scopes and
their use are described in the following sections.
Global
As the name indicates, a
global scope applies to an entire PowerShell instance. Global scope data
is inherited by all child scopes, so any commands, functions, or
scripts that run make use of variables defined in the global scope.
However, global scopes are not shared between different instances of
PowerShell.
The following example shows the $Processes variable being defined as a global variable in the ListProcesses
function. Because the $Processes variable is being defined
globally, checking $Processes.Count after ListProcesses completes returns a count of the number of active
processes at the time ListProcesses was executed:
PS C:\> function ListProcesses {$Global:Processes = get-process}
PS C:\> ListProcesses
PS C:\> $Processes.Count
37
Note
In PowerShell, an
explicit scope indicator can be used to determine the scope a variable
resides in. For instance, if a variable is to reside in the global
scope, it should be defined as $Global:variablename. If an explicit scope indicator isn’t used, a
variable resides in the current scope for which it’s defined.
Local
A local scope is created
dynamically each time a function, filter, or script runs. After a local
scope has finished running, information in it is discarded. A local
scope can read information from the global scope but can’t make changes
to it.
The following example
shows the locally scoped variable $Processes
being defined in the ListProcesses function. After ListProcesses
finishes running, the $ProcessesListProcesses
function. Notice how checking $Processes.Count after the ListProcesses
variable no longer contains any data because it was defined only in the function is finished produces no results:
PS C:\> function ListProcesses {$Processes = get-process}
PS C:\> ListProcesses
PS C:\> $Processes.Count
PS C:\>
Script
A script scope is created whenever a script
file runs and is discarded when the script finishes running. To see an
example of how a script scope works, create the following script and
save it as ListProcesses.ps1:
$Processes = get-process
write-host "Here is the first process:" -Foregroundcolor Yellow
$Processes[0]
After creating the
script file, run it from a PowerShell session. The output should look
similar to this example:
PS C:\> .\ListProcesses.ps1
Here is the first process:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
105 5 1992 4128 32 916 alg
PS C:\> $Processes[0]
Cannot index into a null array.
At line:1 char:12
+ $Processes[0 <<<< ]
PS C:\>
Notice that when the ListProcesses.ps1 script runs, information about the first process
object in the $Processes variable is
written to the console. However, when you try to access information in
the $Processes variable from the
console, an error is returned because the $Processes variable is valid only in the script scope. When
the script finishes running, that scope and all its contents are
discarded.
What if an administrator wants
to use a script in a pipeline or access it as a library file for common
functions? Normally, this isn’t possible because PowerShell discards a
script scope whenever a script finishes running. Luckily, PowerShell
supports the dot-sourcing technique, a term that originally came from
UNIX. Dot sourcing a script file tells PowerShell to load a script scope
into the calling parent’s scope.
To dot source a script file,
simply prefix the script name with a period (dot) when running the
script, as shown here:
PS C:\> . .\coolscript.ps1
Private
A private scope is similar
to a local scope, with one key difference: Definitions in the private
scope aren’t inherited by any child scopes.
The following example
shows the privately scoped variable $Processes defined in the ListProcesses function. Notice that during execution of the ListProcesses$Processes variable isn’t available to the child scope
represented by the script block enclosed by { and } in lines 6–9.
function, the
PS C:\> function ListProcesses {$Private:Processes = get-process
>> write-host "Here is the first process:" -Foregroundcolor Yellow
>> $Processes[0]
>> write-host
>>>> &{
>> write-host "Here it is again:" -Foregroundcolor Yellow
>> $Processes[0]
>> }
>> }
>>PS C:\> ListProcesses
Here is the first process:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
105 5 1992 4128 32 916 alg
Here it is again:
Cannot index into a null array.
At line:7 char:20
+ $Processes[0 <<<< ]
PS C:\>
This example works because it uses
the & call operator. With this call operator, you can execute
fragments of script code in an isolated local scope. This technique is
helpful for isolating a script block and its variables from a parent
scope or, as in this example, isolating a privately scoped variable from
a script block.
Providers and Drives
Most computer systems are used
to store data, often in a structure such as a file system. Because of
the amount of data stored in these structures, processing and finding
information can be unwieldy. Most shells have interfaces, or providers,
for interacting with data stores in a predictable, set manner.
PowerShell also has a set of providers for presenting the contents of
data stores through a core set of cmdlets. You can then use these
cmdlets to browse, navigate, and manipulate data from stores through a
common interface. To get a list of the core cmdlets, use the following
command:
PS C:\> help about_core_commands
...
ChildItem CMDLETS
Get-ChildItem
CONTENT CMDLETS
Add-Content
Clear-Content
Get-Content
Set-Content
...
To view built-in PowerShell providers, use the
following command:
PS C:\> get-psprovider
Name Capabilities Drives
---- ------------ ------
WSMan Credentials {WSMan}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess {C, D, E}
Function ShouldProcess {Function}
Registry ShouldProcess, Transactions {HKLM, HKCU}
Variable ShouldProcess {Variable}
Certificate ShouldProcess {cert}
PS C:\>
The preceding list displays
not only built-in providers, but also the drives each provider currently
supports. A drive is an entity that a provider uses to represent a data
store through which data is made available to the PowerShell session.
For example, the Registry provider creates a PowerShell drive for the
HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER Registry hives.
To see a list of all current
PowerShell drives, use the following command:
PS C:\> get-psdrive
Name Used (GB) Free (GB) Provider Root
---- --------- --------- -------- ----
Alias Alias
C 68.50 107.00 FileSystem C:\
cert Certificate \
D 8.98 1.83 FileSystem D:\
E FileSystem E:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
Variable Variable
WSMan WSMan
PS C:\>