Windows Server 2008 R2 Unleashed (145 page)

example, there’s no reason, other than to encode a script, to create aliases consisting

of only two letters.

724

CHAPTER 21

Automating Tasks Using PowerShell Scripting

Scopes

A scope is a logical boundary in PowerShell that isolates the use of functions and vari-

ables. Scopes can be defined as global, local, script, and private. They function in a hierar-

chy 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

ptg

PS C:\> $Processes.Count

37

NOTE

In PowerShell, an explicit scope indicator can be used to determine the scope a vari-

able 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 $Processes variable

no longer contains any data because it was defined only in the ListProcesses function.

Notice how checking $Processes.Count after the ListProcesses function is finished

produces no results:

PS C:\> function ListProcesses {$Processes = get-process}

PS C:\> ListProcesses

PS C:\> $Processes.Count

PS C:\>

Understanding the PowerShell Basics

725

Script

A script scope is created whenever a script file runs and is discarded when the script

21

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.

ptg

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 function, the

726

CHAPTER 21

Automating Tasks Using PowerShell Scripting

$Processes variable isn’t available to the child scope represented by the script block

enclosed by { and } in lines 6–9.

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:

ptg

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, isolat-

ing 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 informa-

tion 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

Understanding the PowerShell Basics

727

Get-Content

Set-Content

21

...

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:\>

ptg

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:\>

728

CHAPTER 21

Automating Tasks Using PowerShell Scripting

Profiles

A PowerShell profile is a saved collection of settings for customizing the PowerShell envi-

ronment. There are four types of profiles, loaded in a specific order each time PowerShell

starts. The following sections explain these profile types, where they should be located,

and the order in which they are loaded.

The All Users Profile

This profile is located in %windir%\system32\windowspowershell\v1.0\profile.ps1.

Settings in the All Users profile are applied to all PowerShell users on the current machine.

If you plan to configure PowerShell settings across the board for users on a machine, this

is the profile to use.

The All Users Host-Specific Profile

This profile is located in %windir%\system32\windowspowershell\v1.0\ShellID_

profile.ps1. Settings in the All Users host-specific profile are applied to all users of the

current shell (by default, the PowerShell console). PowerShell supports the concept of

multiple shells or hosts. For example, the PowerShell console is a host and the one most

users use exclusively. However, other applications can call an instance of the PowerShell

runtime to access and run PowerShell commands and scripts. An application that does

this is called a hosting application and uses a host-specific profile to control the

ptg

PowerShell configuration. The host-specific profile name is reflected by the host’s ShellID.

In the PowerShell console, the ShellID is the following:

PS C:\ $ShellId

Microsoft.PowerShell

PS C:\

Putting this together, the PowerShell console’s All Users host-specific profile is named

Microsoft.PowerShell_profile.ps1. For other hosts, the ShellID and All Users host-specific

profile names are different. For example, the PowerShell Analyzer (www.powershellana-

lyzer.com) is a PowerShell host that acts as a rich graphical interface for the PowerShell

environment. Its ShellID is PowerShellAnalyzer.PSA, and its All Users host-specific profile

name is PowerShellAnalyzer.PSA_profile.ps1.

The Current User’s Profile

This profile is located in %userprofile%\My Documents\WindowsPowerShell\profile.ps1.

Users who want to control their own profile settings can use the current user’s profile.

Settings in this profile are applied only to the user’s current PowerShell session and don’t

affect any other users.

The Current User’s Host-Specific Profile

This profile is located in %userprofile%\My Documents\WindowsPowerShell\ShellID_

profile.ps1. Like the All Users host-specific profile, this profile type loads settings for

the current shell. However, the settings are user specific.

Understanding the PowerShell Basics

729

NOTE

21

When PowerShell is started for the first time, you might see a message indicating that

scripts are disabled and no profiles are loaded. This behavior can be modified by

changing the PowerShell execution policy.

Security

When WSH was released with Windows 98, it was a godsend for Windows administrators

who wanted the same automation capabilities as their UNIX brethren. At the same time,

virus writers quickly discovered that WSH also opened up a large attack vector against

Windows systems.

Almost anything on a Windows system can be automated and controlled by using WSH,

which is an advantage for administrators. However, WSH doesn’t provide any security in

script execution. If given a script, WSH runs it. Where the script comes from or its purpose

doesn’t matter. With this behavior, WSH became known more as a security vulnerability

than an automation tool.

ptg

Execution Policies

Because of past criticisms of WSH’s security, when the PowerShell team set out to build a

Microsoft shell, the team decided to include an execution policy to mitigate the security

threats posed by malicious code. An execution policy defines restrictions on how

PowerShell allows scripts to run or what configuration files can be loaded. PowerShell has

Other books

Amanda Scott - [Dangerous 02] by Dangerous Angels
Murder of a Needled Knitter by Denise Swanson
Coaching Missy by Ellie Saxx
Mistress of the Storm by Terri Brisbin
What falls away : a memoir by Farrow, Mia, 1945-
Undone by Kristina Lloyd
Thankless in Death by J. D. Robb