Chapter 1. PowerShell Language and Environment
Commands and Expressions
PowerShell breaks any line that you enter into its individual units
(tokens), and then interprets each token in one of
two ways: as a command or as an expression. The difference is subtle:
expressions support logic and flow control statements (such as if
, foreach
,
and throw
), whereas commands do
not.
You will often want to control the way that Windows PowerShell interprets your statements, so Table 1-1 lists the options available to you.
Comments
To create single-line comments, begin a line with the #
character. To create a block (or multiline)
comment, surround the region with the characters <#
and #>.
# This is a regular comment <# This is a block comment function MyTest { "This should not be considered a function" } $myVariable = 10; Block comment ends #> # This is regular script again
Help Comments
PowerShell creates help for your script or function by looking at its comments. If the comments include any supported help tags, PowerShell adds those to the help for your command.
Comment-based help supports the following tags, which are all case-insensitive:
.SYNOPSIS
.DESCRIPTION
.PARAMETER
name
A description of parameter
name
, with one for each parameter you want to describe. While you can write a.PARAMETER
comment for each parameter, PowerShell also supports comments written directly above the parameter (as shown in the solution). Putting parameter help alongside the actual parameter makes it easier to read and maintain..EXAMPLE
An example of this command in use, with one for each example you want to provide. PowerShell treats the line immediately beneath the
.EXAMPLE
tag as the example command. If this line doesn’t contain any text that looks like a prompt, PowerShell adds a prompt before it. It treats lines that follow the initial line as additional output and example commentary..INPUTS
A short summary of pipeline input(s) supported by this command. For each input type, PowerShell’s built-in help follows this convention:
System.String You can pipe a string that contains a path to Get-ChildItem.
.OUTPUTS
A short summary of items generated by this command. For each output type, PowerShell’s built-in help follows this convention:
System.ServiceProcess.ServiceController Get-Service returns objects that represent the services on the computer.
.NOTES
.LINK
A link to a related help topic or command, with one
.LINK
tag per link. If the related help topic is a URL, PowerShell launches that URL when the user supplies the-Online
parameter toGet-Help
for your command.
Although these are all of the supported help tags you are likely to
use, comment-based help also supports tags for some of Get-Help
’s more obscure features: .COMPONENT
, .ROLE
, .FUNCTIONALITY
, .FORWARDHELPTARGETNAME
, .FORWARDHELPCATEGORY
, .REMOTEHELPRUNSPACE
, and .EXTERNALHELP
. For more information about these,
type Get-Help
about_Comment_Based_Help
.
Variables
Windows PowerShell provides several ways to define and access variables, as summarized in Table 1-2.
Booleans
Boolean (true or false) variables are most commonly initialized to
their literal values of $true
and
$false
. When PowerShell evaluates
variables as part of a Boolean expression (for example, an if
statement), though, it maps them to a
suitable Boolean representation, as listed in Table 1-3.
Result | Boolean representation |
| True |
| False |
| False |
Nonzero number | True |
Zero | False |
Nonempty string | True |
Empty string | False |
Empty array | False |
Single-element array | The Boolean representation of its single element |
Multi-element array | True |
Hashtable (either empty or not) | True |
Strings
Windows PowerShell offers several facilities for working with plain-text data.
Literal and Expanding Strings
To define a literal string (one in which no variable or escape expansion occurs), enclose it in single quotes:
$myString = 'hello `t $ENV:SystemRoot'
$myString
gets the actual value
of hello `t $ENV:SystemRoot
.
To define an expanding string (one in which variable and escape expansion occur), enclose it in double quotes:
$myString = "hello `t $ENV:SystemRoot"
$myString
gets a value similar
to hello C:\WINDOWS
.
To include a single quote in a single-quoted string or a double quote in a double-quoted string, include two of the quote characters in a row:
PS > "Hello ""There""!" Hello "There"! PS > 'Hello ''There''!' Hello 'There'!
Note
To include a complex expression inside an expanding string, use a subexpression. For example:
$prompt = "$(get-location) >"
$prompt
gets a value similar
to c:\temp >
.
Accessing the properties of an object requires a subexpression:
$version = "Current PowerShell version is: $($PSVersionTable.PSVersion.Major)"
$version
gets a value similar
to Current PowerShell version is:
3
.
Here Strings
To define a here string (one that may span
multiple lines), place the two characters @"
at the beginning and the two characters
"@
on their own line at the
end.
For example:
$myHereString = @" This text may span multiple lines, and may contain "quotes." "@
Here strings may be of either the literal (single-quoted) or expanding (double-quoted) variety.
Escape Sequences
Windows PowerShell supports escape sequences inside strings, as listed in Table 1-4.
Sequence | Meaning |
| The null character. Often used as a record separator. |
| The alarm character. Generates a beep when displayed on the console. |
| The backspace character. The previous character remains in the string but is overwritten when displayed on the console. |
| A form feed. Creates a page break when printed on most printers. |
| A newline. |
| A carriage return. Newlines in
PowerShell are indicated entirely by the |
| A tab. |
| A vertical tab. |
| A single quote, when in a literal string. |
| A double quote, when in an expanding string. |
| That character, taken literally. |
Numbers
PowerShell offers several options for interacting with numbers and numeric data.
Simple Assignment
To define a variable that holds numeric data, simply assign it as you would other variables. PowerShell automatically stores your data in a format that is sufficient to accurately hold it.
$myInt = 10
$myInt
gets the value of
10
, as a (32-bit) integer.
$myDouble = 3.14
$myDouble
gets the value of
3.14
, as a (53-bit, 9 bits of
precision) double.
To explicitly assign a number as a byte (8-bit) or short (16-bit)
number, use the [byte]
and [int16]
casts:
$myByte = [byte] 128 $myShort = [int16] 32767
To explicitly assign a number as a long (64-bit) integer or decimal (96-bit, 96 bits of precision), use the long and decimal suffixes:
$myLong = 2147483648L
$myLong
gets the value of
2147483648
, as a long integer.
$myDecimal = 0.999D
$myDecimal
gets the value of
0.999
.
PowerShell also supports scientific notation, where e
<number
>
represents multiplying the original number by the
<number
> power of 10:
$myPi = 3141592653e-9
$myPi
gets the value of
3.141592653
.
The data types in PowerShell (integer, long integer, double, and decimal) are built on the .NET data types of the same names.
Administrative Numeric Constants
Since computer administrators rarely get the chance to work with
numbers in even powers of 10, PowerShell offers the numeric constants of
pb
, tb
, gb
,
mb
, and kb
to represent petabytes
(1,125,899,906,842,624), terabytes (1,099,511,627,776), gigabytes
(1,073,741,824), megabytes (1,048,576), and kilobytes (1,024),
respectively:
PS > $downloadTime = (1gb + 250mb) / 120kb PS > $downloadTime 10871.4666666667
Hexadecimal and Other Number Bases
To directly enter a hexadecimal number, use the hexadecimal prefix
0x
:
$myErrorCode = 0xFE4A
$myErrorCode
gets the integer
value 65098
.
The PowerShell scripting language does not natively support other number bases, but its support for interaction with the .NET Framework enables conversion to and from binary, octal, decimal, and hexadecimal:
$myBinary = [Convert]::ToInt32("101101010101", 2)
$myBinary
gets the integer
value of 2901
.
$myOctal = [Convert]::ToInt32("1234567", 8)
$myOctal
gets the integer value
of 342391
.
$myHexString = [Convert]::ToString(65098, 16)
$myHexString
gets the string
value of fe4a
.
$myBinaryString = [Convert]::ToString(12345, 2)
$myBinaryString
gets the string
value of 11000000111001
.
Note
See the section Working with the .NET Framework to learn more about using PowerShell to interact with the .NET Framework.
Large Numbers
To work with extremely large numbers, use the BigInt
class.
[BigInt]::Pow(12345, 123)
To do math with several large numbers, use the [BigInt]
cast for all operands. Be sure to
represent the numbers as strings before converting them to big integers;
otherwise, data loss may occur:
PS > ([BigInt] "98123498123498123894") * ([BigInt] "981234 98123498123894") 9628220883992139841085109029337773723236
Arrays and Lists
Array Definitions
PowerShell arrays hold lists of data. The @()
(array cast) syntax
tells PowerShell to treat the contents between the parentheses as an
array. To create an empty array, type:
$myArray = @()
To define a nonempty array, use a comma to separate its elements:
$mySimpleArray = 1,"Two",3.14
Arrays may optionally be only a single element long:
$myList = ,"Hello"
Or, alternatively (using the array cast syntax):
$myList = @("Hello")
Elements of an array do not need to be all of the same data type,
unless you declare it as a strongly typed array. In the following
example, the outer square brackets define a strongly typed variable (as
mentioned in Variables), and int[]
represents an array of
integers:
[int[]] $myArray = 1,2,3.14
In this mode, PowerShell generates an error if it cannot convert
any of the elements in your list to the required data type. In this
case, it rounds 3.14
to the integer
value of 3:
PS > $myArray[2] 3
Note
To ensure that PowerShell treats collections of uncertain length
(such as history lists or directory listings) as a list, use the list
evaluation syntax @(…)
described in
Commands and Expressions.
Arrays can also be multidimensional jagged arrays (arrays within arrays):
$multiDimensional = @( (1,2,3,4), (5,6,7,8) )
$multiDimensional[0][1]
returns
2, coming from row 0, column 1.
$multiDimensional[1][3]
returns
8, coming from row 1, column 3.
To define a multidimensional array that is not jagged, create a
multidimensional instance of the .NET type. For integers, that would be
an array of System.Int32
:
$multidimensional = New-Object "Int32[,]" 2,4 $multidimensional[0,1] = 2 $multidimensional[1,3] = 8
Array Access
To access a specific element in an array, use the []
operator. PowerShell numbers your array
elements starting at zero. Using $myArray =
1,2,3,4,5,6
as an example:
$myArray[0]
returns 1, the first element in the array.
$myArray[2]
returns 3, the third element in the array.
$myArray[-1]
returns 6, the last element of the array.
$myArray[-2]
returns 5, the second-to-last element of the array.
You can also access ranges of elements in your array:
PS > $myArray[0..2] 1 2 3
returns elements 0 through 2, inclusive.
PS > $myArray[-1..2] 6 1 2 3
returns the final element, wraps around, and returns elements 0 through 2, inclusive. PowerShell wraps around because the first number in the range is positive, and the second number in the range is negative.
PS > $myArray[-1..-3] 6 5 4
returns the last element of the array through to the third-to-last element in the array, in descending order. PowerShell does not wrap around (and therefore scans backward in this case) because both numbers in the range share the same sign.
Array Slicing
You can combine several of the statements in the previous section at once to extract more complex ranges from an array. Use the + sign to separate array ranges from explicit indexes:
$myArray[0,2,4]
returns the elements at indices 0, 2, and 4.
$myArray[0,2+4..5]
returns the elements at indices 0, 2, and 4 through 5, inclusive.
$myArray[,0+2..3+0,0]
returns the elements at indices 0, 2 through 3 inclusive, 0, and 0 again.
Hashtables (Associative Arrays)
Hashtable Definitions
PowerShell hashtables (also called associative arrays) let you associate keys with values. To define a hashtable, use the syntax:
$myHashtable = @{}
You can initialize a hashtable with its key/value pairs when you create it. PowerShell assumes that the keys are strings, but the values may be any data type.
$myHashtable = @{ Key1 = "Value1"; "Key 2" = 1,2,3; 3.14 = "Pi" }
To define a hashtable that retains its insertion order, use the
[ordered]
cast:
$orderedHash = [ordered] @{} $orderedHash["NewKey"] = "Value"
Hashtable Access
To access or modify a specific element in an associative array, you can use either the array-access or property-access syntax:
$myHashtable["Key1"]
returns "Value1"
.
$myHashtable."Key 2"
returns the array 1,2,3
.
$myHashtable["New Item"] = 5
adds "New Item
" to the
hashtable.
$myHashtable."New Item" = 5
also adds "New Item
" to the
hashtable.
XML
PowerShell supports XML as a native data type. To create an XML
variable, cast a string to the [xml]
type:
$myXml = [xml] @" <AddressBook> <Person contactType="Personal"> <Name>Lee</Name> <Phone type="home">555-1212</Phone> <Phone type="work">555-1213</Phone> </Person> <Person contactType="Business"> <Name>Ariel</Name> <Phone>555-1234</Phone> </Person> </AddressBook> "@
PowerShell exposes all child nodes and attributes as properties. When it does this, PowerShell automatically groups children that share the same node type:
$myXml.AddressBook
returns an object that contains a Person
property.
$myXml.AddressBook.Person
returns a list of Person
nodes. Each person node
exposes contactType
,
Name
, and Phone
as
properties.
$myXml.AddressBook.Person[0]
returns the first Person
node.
$myXml.AddressBook.Person[0].ContactType
returns Personal
as the contact
type of the first Person
node.
Simple Operators
Once you’ve defined your data, the next step is to work with it.
Arithmetic Operators
The arithmetic operators let you perform mathematical operations on your data, as shown in Table 1-5.
Note
The System.Math
class in the
.NET Framework offers many powerful operations in addition to the
native operators supported by PowerShell:
PS > [Math]::Pow([Math]::E, [Math]::Pi) 23.1406926327793
See the section Working with the .NET Framework to learn more about using PowerShell to interact with the .NET Framework.
Logical Operators
The logical operators let you compare Boolean values, as shown in Table 1-6.
Binary Operators
The binary operators, listed in Table 1-7,
let you apply the Boolean logical operators bit by bit to the
operator’s arguments. When comparing bits, a 1 represents $true
, whereas a 0 represents $false
.
Other Operators
PowerShell supports several other simple operators, as listed in Table 1-8.
Operator | Meaning |
The replace operator:
Returns a new string, where the text in
By default, PowerShell performs a case-insensitive comparison. The If the regular expression pattern contains named captures or capture groups, the replacement string may reference those as well. For example: PS > "Hello World" -replace "(.*) (.*)",'$2 $1' World Hello If For more information on the details of regular expressions, see Chapter 2. | |
The format operator:
Returns a string where the format items in the format string have been replaced with the text equivalent of the values in the value array. For example: PS > "{0:n0}" -f 1000000000 1,000,000,000 The format string for the format operator
is exactly the format string supported by the .NET For more details about the syntax of the format string, see Chapter 4. | |
The type conversion operator:
Returns For example: PS > 3/2 -as [int] 2 PS > $result = "Hello" -as [int] PS > $result -eq $null True | |
The unary split operator: -split
Breaks the given input string into an array, using
whitespace ( For example: PS > -split " Hello World " Hello World The binary split operator: "Input String" -split " Breaks
the given input string into an array, using the given
For example: PS > "1a2B3" -split "[a-z]+",0,"IgnoreCase" 1 2 3 | |
The unary join operator: -join
Combines the supplied items into a single string, using no separator. For example: PS > -join ("a","b") ab The binary join operator:
Combines
the supplied items into a single string, using
PS > ("a","b") -join ", " a, b |
Comparison Operators
The PowerShell comparison operators, listed in Table 1-9, let you compare expressions against
each other. By default, PowerShell’s comparison operators
are case-insensitive. For all operators where case sensitivity applies, the -i
prefix makes this case insensitivity explicit, whereas the
-c
prefix performs a case-sensitive comparison.
Operator | Meaning |
The equality operator:
For all primitive types, returns When used with arrays, returns all elements in
When used
with any other type, PowerShell uses that type’s | |
The negated equality operator:
For all primitive types, returns When used with arrays, returns all elements in
When used
with any other type, PowerShell returns the negation of that
type’s | |
The greater-than-or-equal operator:
For all primitive types, returns When used
with arrays, returns all elements in
When
used with any other type, PowerShell returns the result of that
object’s | |
The greater-than operator: $leftValue -gt $rightValue For all primitive types, returns When used
with arrays, returns all elements in
When used
with any other type, PowerShell returns the result of that
object’s | |
The in operator:
Returns | |
The negated in operator: Returns | |
The less-than operator:
For all primitive types, returns When used
with arrays, returns all elements in
When used
with any other type, PowerShell returns the result of that
object’s | |
The less-than-or-equal operator:
For all primitive types, returns When used
with arrays, returns all elements in
When used
with any other type, PowerShell returns the result of that
object’s | |
The like operator:
Evaluates the pattern against the target, returning When used with arrays, returns all
elements in The
For example: PS > "Test" -like "[A-Z]e?[tr]" True | |
The negated like operator: Returns | |
| The match operator:
Evaluates the regular expression against the target,
returning When used with arrays, returns all elements
in The
For example: PS > "Hello World" -match "(.*) (.*)" True PS > $matches[1] Hello For more information on the details of regular expressions, see Chapter 2. |
The negated match operator: Returns The | |
The contains operator:
Returns | |
The negated contains operator: Returns | |
The type operator:
Returns | |
The negated type operator: Returns |
Conditional Statements
Conditional statements in PowerShell let you change the flow of execution in your script.
if, elseif, and else Statements
if(condition)
{ statement block } elseif(condition)
{ statement block } else { statement block }
If condition
evaluates to $true
, PowerShell executes the statement block
you provide. Then, it resumes execution at the end of the if/elseif/else
statement list. PowerShell
requires the enclosing braces around the statement block, even if the
statement block contains only one statement.
Note
See Simple Operators and Comparison Operators for a discussion on how PowerShell evaluates expressions as conditions.
If condition
evaluates to $false
, PowerShell evaluates any following
(optional) elseif
conditions until
one matches. If one matches, PowerShell executes the statement block
associated with that condition, and then resumes execution at the end of
the if/elseif/else
statement
list.
For example:
$textToMatch = Read-Host "Enter some text" $matchType = Read-Host "Apply Simple or Regex matching?" $pattern = Read-Host "Match pattern" if($matchType -eq "Simple") { $textToMatch -like $pattern } elseif($matchType -eq "Regex") { $textToMatch -match $pattern } else { Write-Host "Match type must be Simple or Regex" }
If none of the conditions evaluate to $true
, PowerShell executes the statement block
associated with the (optional) else
clause, and then resumes execution at the end of the if/elseif/else
statement list.
switch Statements
switchoptions expression
{comparison value
{statement block
} -or- {comparison expression
} {statement block
} (...) default {statement block
} }
or:
switchoptions
-filefilename
{comparison value
{statement block
} -or {comparison expression
} {statement block
} (...) default {statement block
} }
When PowerShell evaluates a switch
statement, it
evaluates expression
against the statements in the switch body.
If expression
is a list of
values, PowerShell evaluates each item against the statements in the switch body. If you
specify the
-file
option, PowerShell treats the lines in
the file as though they were a list of items in expression
.
The comparison value
statements let you
match the current input item against the pattern specified by
comparison value
. By default, PowerShell
treats this as a case-insensitive
exact match, but the options you provide to the switch
statement can change this, as shown in
Table 1-10.
Option | Meaning |
| Case-sensitive match. With this option active, PowerShell executes the associated statement block only
if the current input item exactly matches the value specified by
|
| Exact match With this option active, PowerShell executes the associated statement block only
if the current input item exactly matches the value specified by
|
| Regular-expression match With this option active, PowerShell executes the
associated statement block only if the current input item
matches the regular expression specified by
|
| Wildcard match With this option active, PowerShell executes the associated statement block only
if the current input item matches the wildcard
specified by The wildcard match supports the following simple wildcard characters:
This match is case-insensitive. |
The {
comparison
expression
}
statements
let you process the current input item, which is stored in the $_
(or $PSItem
) variable, in an arbitrary script
block. When it processes a {
comparison expression
}
statement, PowerShell executes the
associated statement block only if {
comparison expression
}
evaluates to $true
.
PowerShell executes the statement block associated with the
(optional) default
statement if no
other statements in the switch
body
match.
When processing a switch
statement, PowerShell tries to match the current input object against
each statement in the switch
body,
falling through to the next statement even after one or more have
already matched. To have PowerShell discontinue the current comparison
(but retry the switch statement with the next input object), include a
continue
statement as the last
statement in the statement block. To have PowerShell exit a switch
statement completely after it processes
a match, include a break
statement as
the last statement in the statement block.
For example:
$myPhones = "(555) 555-1212","555-1234" switch -regex ($myPhones) { { $_.Length -le 8 } { "Area code was not specified"; break } { $_.Length -gt 8 } { "Area code was specified" } "\((555)\).*" { "In the $($matches[1]) area code" } }
produces the output:
Area code was specified In the 555 area code Area code was not specified
Note
See Looping Statements for more information
about the break
statement.
By default, PowerShell treats this as a case-insensitive exact
match, but the options you provide to the switch
statement can change this.
Looping Statements
Looping statements in PowerShell let you execute groups of statements multiple times.
for Statement
:loop_label
for (initialization
;condition
;increment
) {statement block
}
When PowerShell executes a for
statement, it first executes the expression given by
initialization
. It next evaluates
condition
. If
condition
evaluates to $true
, PowerShell executes the given statement
block. It then executes the expression given by increment
. PowerShell continues to
execute the statement block and increment
statement as long as condition
evaluates to
$true
.
For example:
for($counter = 0; $counter -lt 10; $counter++) { Write-Host "Processing item $counter" }
The break
and continue
statements (discussed later in this appendix) can specify the
loop_label
of any enclosing looping statement as their target.
foreach Statement
:loop_label
foreach (variable in expression
) {statement block
}
When PowerShell executes a foreach
statement, it executes the pipeline
given by expression
—for example, Get-Process | Where-Object {$_.Handles -gt
500}
or 1..10
. For each
item produced by the expression, it assigns that item to the variable
specified by variable
and then executes the
given statement block. For example:
$handleSum = 0; foreach($process in Get-Process | Where-Object { $_.Handles -gt 500 }) { $handleSum += $process.Handles } $handleSum
The break
and continue
statements (discussed later in this
appendix) can specify the loop_label
of any
enclosing looping statement as their target. In addition to the foreach
statement,
PowerShell also offers the Foreach-Object
cmdlet with similar
capabilities.
while Statement
:loop_label
while(condition
) {statement block
}
When PowerShell executes a while
statement, it first
evaluates the expression given by condition
. If this expression
evaluates to $true
, PowerShell executes the given statement block.
PowerShell continues to execute the statement block as long as condition
evaluates to $true
. For example:
$command = ""; while($command -notmatch "quit") { $command = Read-Host "Enter your command" }
The break
and continue
statements (discussed later in this
appendix) can specify the loop_label
of any
enclosing looping statement as their target.
do … while Statement/do … until Statement
:loop_label
do {statement block
} while(condition
)
or
:loop_label
do {statement block
} until(condition
)
When PowerShell executes a do … while
or do … until
statement, it first executes the given statement
block. In a do … while
statement, PowerShell continues to
execute the statement block as long as condition
evaluates to
$true
. In a do …
until
statement, PowerShell continues to execute the statement as long as
condition
evaluates to $false
. For example:
$validResponses = "Yes","No" $response = "" do { $response = read-host "Yes or No?" } while($validResponses -notcontains $response) "Got it." $response = "" do { $response = read-host "Yes or No?" } until($validResponses -contains $response) "Got it."
The break
and continue
statements (discussed later) can specify the
loop_label
of any enclosing looping statement as their
target.
Flow Control Statements
PowerShell supports two statements to help you control flow within
loops: break
and continue
.
break
The break
statement halts execution of the current
loop. PowerShell then resumes execution at the end
of the current looping statement, as though the looping statement had completed naturally.
For example:
for($counter = 0; $counter -lt 5; $counter++) { for($counter2 = 0; $counter2 -lt 5; $counter2++) { if($counter2 -eq 2) { break } Write-Host "Processing item $counter,$counter2" } }
produces the output:
Processing item 0,0 Processing item 0,1 Processing item 1,0 Processing item 1,1 Processing item 2,0 Processing item 2,1 Processing item 3,0 Processing item 3,1 Processing item 4,0 Processing item 4,1
If you specify a label with the break
statement—for example, break outer_
loop
—PowerShell halts the execution of that
loop instead. For example:
:outer_loop for($counter = 0; $counter -lt 5; $counter++) { for($counter2 = 0; $counter2 -lt 5; $counter2++) { if($counter2 -eq 2) { break outer_loop } Write-Host "Processing item $counter,$counter2" } }
produces the output:
Processing item 0,0 Processing item 0,1
continue
The continue
statement skips
execution of the rest of the current statement block. PowerShell then
continues with the next iteration of the current looping statement, as
though the statement block had completed naturally. For
example:
for($counter = 0; $counter -lt 5; $counter++) { for($counter2 = 0; $counter2 -lt 5; $counter2++) { if($counter2 -eq 2) { continue } Write-Host "Processing item $counter,$counter2" } }
produces the output:
Processing item 0,0 Processing item 0,1 Processing item 0,3 Processing item 0,4 Processing item 1,0 Processing item 1,1 Processing item 1,3 Processing item 1,4 Processing item 2,0 Processing item 2,1 Processing item 2,3 Processing item 2,4 Processing item 3,0 Processing item 3,1 Processing item 3,3 Processing item 3,4 Processing item 4,0 Processing item 4,1 Processing item 4,3 Processing item 4,4
If you specify a label with the continue
statement—for example, continue outer_
loop
—PowerShell continues with the next
iteration of that loop instead.
For example:
:outer_loop for($counter = 0; $counter -lt 5; $counter++) { for($counter2 = 0; $counter2 -lt 5; $counter2++) { if($counter2 -eq 2) { continue outer_loop } Write-Host "Processing item $counter,$counter2" } }
produces the output:
Processing item 0,0 Processing item 0,1 Processing item 1,0 Processing item 1,1 Processing item 2,0 Processing item 2,1 Processing item 3,0 Processing item 3,1 Processing item 4,0 Processing item 4,1
Workflow-Specific Statements
Within a workflow, PowerShell supports four statements not supported in traditional
PowerShell scripts: InlineScript
, Parallel
, Sequence
, and foreach -parallel
.
InlineScript
The InlineScript
keyword defines an island of
PowerShell script that will be invoked as a unit, and with traditional PowerShell scripting semantics. For example:
workflow MyWorkflow { ## Method invocation not supported in a workflow ## [Math]::Sqrt(100) InlineScript { ## Supported in an InlineScript [Math]::Sqrt(100) } }
Parallel/Sequence
The Parallel
keyword
specifies that all statements within the statement block should run in
parallel. To group statements that should be run as a unit, use the
Sequence
keyword:
workflow MyWorkflow { Parallel { InlineScript { Start-Sleep -Seconds 2; "One thing run in parallel" } InlineScript { Start-Sleep -Seconds 4; "Another thing run in parallel" } InlineScript { Start-Sleep -Seconds 3; "A third thing run in parallel" } Sequence { Start-Sleep -Seconds 1 "A fourth" "and fifth thing run as a unit, in parallel" } } }
Working with the .NET Framework
One feature that gives PowerShell its incredible reach into both system administration and application development is its capability to leverage Microsoft’s enormous and broad .NET Framework.
Work with the .NET Framework in PowerShell comes mainly by way of one of two tasks: calling methods or accessing properties.
Static Methods
To call a static method on a class, type:
[ClassName
]::MethodName
(parameter list
)
For example:
PS > [System.Diagnostics.Process]::GetProcessById(0)
gets the process with the ID of 0 and displays the following output:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 0 0 0 16 0 0 Idle
Instance Methods
To call a method on an instance of an object, type:
$objectReference
.MethodName
(parameter list
)
For example:
PS > $process = [System.Diagnostics.Process]:: GetProcessById(0) PS > $process.Refresh()
This stores the process with ID of 0 into the $process
variable. It then calls the Refresh()
instance method on that specific
process.
Explicitly Implemented Interface Methods
To call a method on an explictly implemented interface:
([Interface
]$objectReference
).MethodName
(parameter list
)
For example:
PS > ([IConvertible] 123).ToUint16($null)
Static Properties
To access a static property on a class, type:
[ClassName
]::PropertyName
or:
[ClassName
]::PropertyName
=value
For example, the [System.DateTime]
class provides a Now
static property that returns the current
time:
PS > [System.DateTime]::Now Sunday, July 16, 2006 2:07:20 PM
Although this is rare, some types let you set the value of some static properties.
Instance Properties
To access an instance property on an object, type:
$objectReference
.PropertyName
or:
$objectReference
.PropertyName
=value
For example:
PS > $today = [System.DateTime]::Now PS > $today.DayOfWeek Sunday
This stores the current date in the $today
variable. It then calls the DayOfWeek
instance property on that specific
date.
Learning About Types
The two primary avenues for learning about classes and types are
the Get-Member
cmdlet and the
documentation for the .NET Framework.
The Get-Member cmdlet
To learn what methods and properties a given type supports, pass
it through the Get-Member
cmdlet,
as shown in Table 1-11.
.NET Framework documentation
Another source of information about the classes in the .NET Framework is the documentation itself, available through the search facilities at MSDN.
Typical documentation for a class first starts with a general overview, and then provides a hyperlink to the members of the class—the list of methods and properties it supports.
Note
To get to the documentation for the members quickly, search for them more explicitly by adding the term “members” to your MSDN search term:
classname
members
The documentation for the members of a class lists their constructors, methods, properties, and more. It uses an S icon to represent the static methods and properties. Click the member name for more information about that member, including the type of object that the member produces.
Type Shortcuts
When you specify a type name, PowerShell lets you use a short form for some of the most common types, as listed in Table 1-12.
Type shortcut | Full classname |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
Creating Instances of Types
$objectReference
= New-ObjectTypeName
parameters
Although static methods and properties of a class generate
objects, you will often want to create them explicitly yourself.
PowerShell’s New-Object
cmdlet lets
you create an instance of the type you specify. The parameter list must
match the list of parameters accepted by one of the type’s constructors,
as documented on MSDN.
For example:
$webClient = New-Object Net.WebClient $webClient.DownloadString("http://search.msn.com")
If the type represents a generic type, enclose its type parameters in square brackets:
PS > $hashtable = New-Object "System.Collections.Generic. Dictionary[String,Bool]" PS > $hashtable["Test"] = $true
Most common types are available by default. However, many types are available only after you load the library (called the assembly) that defines them. The MSDN documentation for a class includes the assembly that defines it.
To load an assembly, use the -AssemblyName
parameter of the Add-Type
cmdlet:
PS > Add-Type -AssemblyName System.Web PS > [Web.HttpUtility]::UrlEncode("http://www.bing.com") http%3a%2f%2fwww.bing.com
Interacting with COM Objects
PowerShell lets you access methods and properties on COM objects
the same way you would interact with objects from the .NET Framework. To
interact with a COM object, use its ProgId
with the -ComObject
parameter (often shortened to
-Com
) on New-Object
:
PS > $shell = New-Object -Com Shell.Application PS > $shell.Windows() | Select-Object LocationName,LocationUrl
For more information about the COM objects most useful to system administrators, see Chapter 8.
Extending Types
PowerShell supports two ways to add your own methods and
properties to any type: the Add-Member
cmdlet and a custom types extension
file.
The Add-Member cmdlet
The Add-Member
cmdlet lets
you dynamically add methods, properties, and more to an object. It
supports the extensions shown in Table 1-13.
Custom type extension files
While the Add-Member
cmdlet
lets you customize individual objects, PowerShell also supports
configuration files that let you customize all objects of a given
type. For example, you might want to add a Reverse()
method to all strings or a
HelpUrl
property (based on the MSDN
Url Aliases) to all types.
PowerShell adds several type extensions to the file
types.ps1xml, in the PowerShell installation
directory. This file is useful as a source of examples, but you should
not modify it directly. Instead, create a new one and use the Update-TypeData
cmdlet to load your
customizations. The following command loads
Types.custom.ps1xml from the same directory as
your profile:
$typesFile = Join-Path (Split-Path $profile) "Types. Custom.Ps1Xml" Update-TypeData -PrependPath $typesFile
Writing Scripts, Reusing Functionality
When you want to start packaging and reusing your commands, the best place to put them is in scripts, functions, and script blocks. A script is a text file that contains a sequence of PowerShell commands. A function is also a sequence of PowerShell commands but is usually placed within a script to break it into smaller, more easily understood segments. A script block is a function with no name. All three support the same functionality, except for how you define them.
Writing Commands
Writing scripts
To write a script, write your PowerShell commands in a text editor and save the file with a .ps1 extension.
Writing functions
Functions let you package blocks of closely related commands into a single unit that you can access by name.
function SCOPE:name(parameters)
{statement block
}
or:
filter SCOPE:name(parameters)
{statement block
}
Valid scope names are global
(to create a function
available to the entire shell), script
(to create a function available only to the current
script), local
(to create a function available
only to the current scope and subscopes), and
private
(to create a function available only to the
current scope). The default scope is the local
scope,
which follows the same rules as those of default variable scopes.
The content of a function’s statement block follows the same
rules as the content of a script. Functions support the $args
array, formal parameters, the $input
enumerator, cmdlet keywords, pipeline
output, and equivalent return semantics.
Note
A common mistake is to call a function as you would call a method:
$result = GetMyResults($item1, $item2)
PowerShell treats functions as it treats scripts and other commands, so this should instead be:
$result = GetMyResults $item1 $item2
The first command passes an array that contains the items
$item1
and $item2
to the GetMyResults
function.
A filter is simply a function where the statements are treated
as though they are contained within a process
statement block. For more
information about process
statement
blocks, see Cmdlet keywords in commands.
Note
Commands in your script can access only functions that have already been defined. This can often make large scripts difficult to understand when the beginning of the script is composed entirely of helper functions. Structuring a script in the following manner often makes it more clear:
function Main { (...) HelperFunction (...) } function HelperFunction { (...) } . Main
Writing script blocks
$objectReference =
{
statement block
}
PowerShell supports script blocks, which act exactly like
unnamed functions and scripts. Like both scripts and functions, the
content of a script block’s statement block follows the same rules as
the content of a function or script. Script blocks support the
$args
array, formal parameters, the
$input
enumerator, cmdlet keywords,
pipeline output, and equivalent return semantics.
As with both scripts and functions, you can either invoke or
dot-source a script block. Since a script block does not have a name,
you either invoke it directly (&
{ "Hello"
}) or invoke the variable (&
$objectReference
) that contains
it.
Running Commands
There are two ways to execute a command (script, function, or script block): by invoking it or by dot-sourcing it.
Invoking
Invoking a command runs the commands inside it. Unless
explicitly defined with the GLOBAL
scope keyword, variables and functions defined in the script do not
persist once the script exits.
Note
By default, a security feature in PowerShell called the
Execution Policy prevents scripts from running. When you want to
enable scripting in PowerShell, you must change this setting. To
understand the different execution policies available to you, type
Get-Help about_signing
. After
selecting an execution policy, use the Set-ExecutionPolicy
cmdlet to configure
it:
Set-ExecutionPolicy RemoteSigned
If the command name has no spaces, simply type its name:
c:\temp\Invoke-Commands.ps1parameter1 parameter2 ...
Invoke-MyFunctionparameter1 parameter2 ...
You can use either a fully qualified path or a path relative to the current location. If the script is in the current directory, you must explicitly say so:
.\Invoke-Commands.ps1 parameter1 parameter2 ...
If the command’s name has a space (or the command has no name,
in the case of a script block), you invoke the command by using the
invoke/call operator (&
) with
the command name as the parameter.
& "C:\Script Directory\Invoke-Commands.ps1" parameter1
parameter2 ...
Script blocks have no name, so you place the variable holding them after the invocation operator:
$scriptBlock = { "Hello World" }
& $scriptBlock parameter1 parameter2 ...
If you want to invoke the command within the context of a module, provide a reference to that module as part of the invocation:
$module = Get-Module PowerShellCookbook &$module
Invoke-MyFunctionparameter1 parameter2 ...
&$module
$scriptBlockparameter1 parameter2 ...
Dot-sourcing
Dot-sourcing a command runs the commands inside it. Unlike simply invoking a command, variables and functions defined in the script do persist after the script exits.
You invoke a script by using the dot operator (.
) and providing the command name as the
parameter:
. "C:\Script Directory\Invoke-Commands.ps1"Parameters
. Invoke-MyFunctionparameters
. $scriptBlockparameters
When dot-sourcing a script, you can use either a fully qualified path or a path relative to the current location. If the script is in the current directory, you must explicitly say so:
. .\Invoke-Commands.ps1 Parameters
If you want to dot-source the command within the context of a module, provide a reference to that module as part of the invocation:
$module = Get-Module PowerShellCookbook .$module
Invoke-MyFunctionparameters
.$module
$scriptBlockparameters
Parameters
Commands that require or support user input do so through
parameters. You can use the Get-Command
cmdlet to
see the parameters supported by a command:
PS > Get-Command Stop-Process -Syntax Stop-Process [-Id] <int[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>] Stop-Process -Name <string[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>] Stop-Process [-InputObject] <Process[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
In
this case, the supported parameters of the Stop-Process
command are Id
, Name
, InputObject
, PassThru
, Force
, WhatIf
, and Confirm
.
To supply a value for a parameter, use a dash character, followed by the parameter name, followed by a space, and then the parameter value.
Stop-Process -Id 1234
If the parameter value contains spaces, surround it with quotes:
Stop-Process -Name "Process With Spaces"
If a variable contains a value that you want to use for a parameter, supply that through PowerShell’s regular variable reference syntax:
$name = "Process With Spaces" Stop-Process -Name $name
If you want to use other PowerShell language elements as a parameter value, surround the value with parentheses:
Get-Process -Name ("Power" + "Shell")
You only need to supply enough of the parameter name to disambiguate it from the rest of the parameters.
Stop-Process -N "Process With Spaces"
If
a command’s syntax shows the parameter name in square brackets (such
as [-Id]
), then it is
positional and you may omit the parameter name
and supply only the value. PowerShell supplies these unnamed values to
parameters in the order of their position.
Stop-Process 1234
Rather than explicitly providing parameter names and values, you can provide a hashtable that defines them and use the splatting operator:
$parameters = @{ Path = "c:\temp" Recurse = $true } Get-ChildItem @parameters
To define the default value to be used for the parameter of a
command (if the parameter value is not specified directly), assign a
value to the PSDefaultParameterValues
hashtable. The keys
of this hashtable are command names and parameter names, separated by
a colon. Either (or both) may use wildcards. The values of this
hashtable are either simple parameter values, or script blocks that
will be evaluated dynamically.
PS > $PSDefaultParameterValues["Get-Process:ID"] = $pid PS > Get-Process PS > $PSDefaultParameterValues["Get-Service:Name"] = { Get-Service -Name * | Foreach-Object Name | Get-Random } PS > Get-Service
Providing Input to Commands
PowerShell offers several options for processing input to a command.
Argument array
To access the command-line arguments by position, use the
argument array that PowerShell
places in the $args
special
variable:
$firstArgument = $args[0] $secondArgument = $args[1] $argumentCount = $args.Count
Formal parameters
To define a command with simple parameter support:
param([TypeName] $VariableName
=Default
, ... )
To define one with support for advanced functionality:
[CmdletBinding(cmdlet behavior customizations
)] param( [Parameter(Mandatory = $true, Position = 1, ...
)] [Alias("MyParameterAlias
"] [...][TypeName] $VariableName
=Default
, ... )
Formal parameters let you benefit from some of the many benefits of PowerShell’s consistent command-line parsing engine.
PowerShell exposes your parameter names (for example, $VariableName
) the same way that it exposes
parameters in cmdlets. Users need to type only enough of your parameter name to
disambiguate it from the rest of the parameters.
If you define a command with simple parameter support, PowerShell attempts to assign the input to your parameters by their position if the user does not type parameter names.
When you add the [CmdletBinding()]
attribute,
[Parameter()]
attribute, or any of the validation attributes, PowerShell adds support for advanced
parameter validation.
Command behavior customizations
The elements of the [CmdletBinding()]
attribute describe how
your script or function interacts with the system.
SupportsShouldProcess = $true
If
$true
, enables the-WhatIf
and-Confirm
parameters, which tells the user that your command modifies the system and can be run in one of these experimental modes. When specified, you must also call the$psCmdlet.ShouldProcess()
method before modifying system state. When not specified, the default is$false
.DefaultParameterSetName =
name
Defines the default parameter set name of this command. This is used to resolve ambiguities when parameters declare multiple sets of parameters and the user input doesn’t supply enough information to pick between available parameter sets. When not specified, the command has no default parameter set name.
ConfirmImpact =
"High
"Defines this command as one that should have its confirmation messages (generated by the
$psCmdlet.ShouldProcess()
method) shown by default. More specifically, PowerShell defines three confirmation impacts:Low
,Medium
, andHigh
. PowerShell generates the cmdlet’s confirmation messages automatically whenever the cmdlet’s impact level is greater than the preference variable. When not specified, the command’s impact isMedium
.
Parameter attribute customizations
The elements of the [Parameter()]
attribute mainly define how
your parameter behaves in relation to other parameters. All elements
are optional.
Mandatory = $true
Defines the parameter as mandatory. If the user doesn’t supply a value to this parameter, PowerShell automatically prompts him for it. When not specified, the parameter is optional.
Position =
position
Defines the position of this parameter. This applies when the user provides parameter values without specifying the parameter they apply to (e.g.,
Argument2
inInvoke-MyFunction -
). PowerShell supplies these values to parameters that have defined aParam1
Argument1
Argument2
Position
, from lowest to highest. When not specified, the name of this parameter must be supplied by the user.ParameterSetName =
name
Defines this parameter as a member of a set of other related parameters. Parameter behavior for this parameter is then specific to this related set of parameters, and the parameter exists only in the parameter sets that it is defined in. This feature is used, for example, when the user may supply only a Name or ID. To include a parameter in two or more specific parameter sets, use two or more
[Parameter()]
attributes. When not specified, this parameter is a member of all parameter sets.ValueFromPipeline = $true
Declares this parameter as one that directly accepts pipeline input. If the user pipes data into your script or function, PowerShell assigns this input to your parameter in your command’s
process {}
block. When not specified, this parameter does not accept pipeline input directly.ValueFromPipelineByPropertyName = $true
Declares this parameter as one that accepts pipeline input if a property of an incoming object matches its name. If this is true, PowerShell assigns the value of that property to your parameter in your command’s
process {}
block. When not specified, this parameter does not accept pipeline input by property name.ValueFromRemainingArguments = $true
Declares this parameter as one that accepts all remaining input that has not otherwise been assigned to positional or named parameters. Only one parameter can have this element. If no parameter declares support for this capability, PowerShell generates an error for arguments that cannot be assigned.
Parameter validation attributes
In addition to the [Parameter()]
attribute,
PowerShell lets you apply other attributes that add behavior or validation constraints to
your parameters. All validation attributes are optional.
[Alias("
name
")]
Defines an alternate name for this parameter. This is especially helpful for long parameter names that are descriptive but have a more common colloquial term. When not specified, the parameter can be referred to only by the name you originally declared.
[AllowNull()]
Allows this parameter to receive
$null
as its value. This is required only for mandatory parameters. When not specified, mandatory parameters cannot receive$null
as their value, although optional parameters can.[AllowEmptyString()]
Allows this string parameter to receive an empty string as its value. This is required only for mandatory parameters. When not specified, mandatory string parameters cannot receive an empty string as their value, although optional string parameters can. You can apply this to parameters that are not strings, but it has no impact.
[AllowEmptyCollection()]
Allows this collection parameter to receive an empty collection as its value. This is required only for mandatory parameters. When not specified, mandatory collection parameters cannot receive an empty collection as their value, although optional collection parameters can. You can apply this to parameters that are not collections, but it has no impact.
[ValidateCount(
lower limit
,upper limit
)]
Restricts the number of elements that can be in a collection supplied to this parameter. When not specified, mandatory parameters have a lower limit of one element. Optional parameters have no restrictions. You can apply this to parameters that are not collections, but it has no impact.
[ValidateLength(
lower limit
,upper limit
)]
Restricts the length of strings that this parameter can accept. When not specified, mandatory parameters have a lower limit of one character. Optional parameters have no restrictions. You can apply this to parameters that are not strings, but it has no impact.
[ValidatePattern("
regular expression
")]
Enforces a pattern that input to this string parameter must match. When not specified, string inputs have no pattern requirements. You can apply this to parameters that are not strings, but it has no impact.
[ValidateRange(
lower limit
,upper limit
)]
Restricts the upper and lower limit of numerical arguments that this parameter can accept. When not specified, parameters have no range limit. You can apply this to parameters that are not numbers, but it has no impact.
[ValidateScript( {
script block
} )]
Ensures that input supplied to this parameter satisfies the condition that you supply in the script block. PowerShell assigns the proposed input to the
$_
(or$PSItem
) variable, and then invokes your script block. If the script block returns$true
(or anything that can be converted to$true
, such as nonempty strings), PowerShell considers the validation to have been successful.[ValidateSet("
First Option
", "
Second Option
",
..., "
Last Option
")]
Ensures that input supplied to this parameter is equal to one of the options in the set. PowerShell uses its standard meaning of equality during this comparison: the same rules used by the
-eq
operator. If your validation requires nonstandard rules (such as case-sensitive comparison of strings), you can instead write the validation in the body of the script or function.[ValidateNotNull()]
Ensures that input supplied to this parameter is not null. This is the default behavior of mandatory parameters, so this is useful only for optional parameters. When applied to string parameters, a
$null
parameter value gets instead converted to an empty string.[ValidateNotNullOrEmpty()]
Ensures that input supplied to this parameter is not null or empty. This is the default behavior of mandatory parameters, so this is useful only for optional parameters. When applied to string parameters, the input must be a string with a length greater than one. When applied to collection parameters, the collection must have at least one element. When applied to other types of parameters, this attribute is equivalent to the
[ValidateNotNull()]
attribute.
Pipeline input
To access the data being passed to your command via the
pipeline, use the input enumerator that PowerShell places in the
$input
special variable:
foreach($element in $input) { "Input was: $element" }
The $input
variable is a .NET
enumerator over the pipeline input. Enumerators support streaming
scenarios very efficiently but do not let you access arbitrary
elements as you would with an array. If you want to process their
elements again, you must call the Reset()
method on the $input
enumerator once you reach the
end.
If you need to access the pipeline input in an unstructured way, use the following command to convert the input enumerator to an array:
$inputArray = @($input)
Cmdlet keywords in commands
When pipeline input is a core scenario of your command, you can
include statement blocks labeled begin
, process
, and end
:
param(...) begin { ... } process { ... } end { ... }
PowerShell executes the begin
statement when it loads your command, the process
statement for each item passed down
the pipeline, and the end
statement
after all pipeline input has been processed. In the process
statement block, the $_
(or $PSItem
) variable represents the current
pipeline object.
When you write a command that includes these keywords, all the commands in your script must be contained within the statement blocks.
Retrieving Output from Commands
PowerShell provides three primary ways to retrieve output from a command.
Pipeline output
any command
The return value/output of a script is any data that it generates but does not capture. If a command contains:
"Text Output" 5*5
then assigning the output of that command to a variable creates
an array with the two values Text
Output
and 25
.
Return statement
return value
The statement:
return $false
is simply a short form for pipeline output:
$false return
Exit statement
exit errorlevel
The exit
statement returns an
error code from the current command or instance of PowerShell. If
called anywhere in a script (inline, in a function, or in a script
block), it exits the script. If called outside of a script (for
example, a function), it exits PowerShell. The exit
statement sets the $LastExitCode
automatic variable to
errorLevel
. In turn, that sets the $?
automatic variable to $false
if
errorLevel
is not zero.
Help Documentation
PowerShell automatically generates help content out of specially tagged comments in your command:
<# .SYNOPSIS Runs a ... .EXAMPLE PS > ... #> param( ## Help content for the Param1 parameter $Param1 )
Help-specific comments must be the only comments in a comment block. If PowerShell discovers a nonhelp comment, it discontinues looking for comments in that comment block. If you need to include nonhelp comments in a comment block, place them in a separate block of comments. The following are the most typical help comments used in a comment block:
.SYNOPSIS
A short summary of the command, ideally a single sentence.
.DESCRIPTION
A more detailed description of the command.
.PARAMETER
name
A description of parameter
name
, with one for each parameter you want to describe. While you can write a.PARAMETER
comment for each parameter, PowerShell also supports comments written directly above the parameter. Putting parameter help alongside the actual parameter makes it easier to read and maintain..EXAMPLE
An example of this command in use, with one for each example you want to provide. PowerShell treats the line immediately beneath the
.EXAMPLE
tag as the example command. If this line doesn’t contain any text that looks like a prompt, PowerShell adds a prompt before it. It treats lines that follow the initial line as additional output and example commentary..INPUTS
A short summary of pipeline input(s) supported by this command. For each input type, PowerShell’s built-in help follows this convention:
System.String You can pipe a string that contains a path to Get-ChildItem.
.OUTPUTS
A short summary of items generated by this command. For each output type, PowerShell’s built-in help follows this convention:
System.ServiceProcess.ServiceController Get-Service returns objects that represent the services on the computer.
.NOTES
Any additional notes or remarks about this command.
.LINK
A link to a related help topic or command, with one
.LINK
tag per link. If the related help topic is a URL, PowerShell launches that URL when the user supplies the-Online
parameter toGet-Help
for your command.
Managing Errors
PowerShell supports two classes of errors:
nonterminating and terminating.
It collects both types of errors as a list in the $error
automatic variable.
Nonterminating Errors
Most errors are nonterminating errors, in that they do not halt execution of the current cmdlet, script, function, or pipeline. When a command outputs an error (via PowerShell’s error-output facilities), PowerShell writes that error to a stream called the error output stream.
You can output a nonterminating error using the Write-Error
cmdlet (or the WriteError()
API when
writing a cmdlet).
The $ErrorActionPreference
automatic variable lets you control how PowerShell handles
nonterminating errors. It supports the following values, shown in Table 1-14.
Value | Meaning |
| Do not display errors, and do not add them to the
|
| Do not display errors, but add them to the |
| Treat nonterminating errors as terminating errors. |
| Display errors, but continue execution of the current cmdlet, script, function, or pipeline. This is the default. |
| Display a prompt that asks how PowerShell should treat this error. |
Most cmdlets let you configure this explicitly by passing one of
these values to the ErrorAction
parameter.
Terminating Errors
A terminating error halts execution of the current cmdlet, script, function, or pipeline. If a command (such as a cmdlet or .NET method call) generates a structured exception (for example, if you provide a method with parameters outside their valid range), PowerShell exposes this as a terminating error. PowerShell also generates a terminating error if it fails to parse an element of your script, function, or pipeline.
You can generate a terminating error in your script using the
throw
keyword:
throw message
Note
In your own scripts and cmdlets, generate terminating errors only when the fundamental intent of the operation is impossible to accomplish. For example, failing to execute a command on a remote server should be considered a nonterminating error, whereas failing to connect to the remote server altogether should be considered a terminating error.
You can intercept terminating errors through the try
, catch
,
and finally
statements, as supported
by many other programming languages:
try {statement block
} catch[exception type]
{error handling block
} catch[alternate exception type]
{alternate error handling block
} finally {cleanup block
}
After a try
statement,
you must provide a catch
statement, a
finally
statement, or both. If you
specify an exception type (which is optional), you may specify more than
one catch
statement to handle
exceptions of different types. If you specify an exception type, the
catch
block applies only to
terminating errors of that type.
PowerShell also lets you intercept terminating errors if you
define a trap
statement before
PowerShell encounters that error:
trap[exception type]
{statement block
[continue or break]
}
If you specify an exception type, the trap
statement applies only to terminating
errors of that type.
Within a catch block or trap statement, the $_
(or $PSItem
) variable represents the current
exception or error being processed.
If specified, the continue
keyword tells PowerShell to continue processing your script, function,
or pipeline after the point at which it encountered the terminating
error.
If specified, the break
keyword
tells PowerShell to halt processing the rest of your script, function,
or pipeline after the point at which it encountered the terminating
error. The default mode is break
, and
it applies if you specify neither break
nor continue
.
Formatting Output
Pipeline
|Formatting Command
When objects reach the end of the output pipeline, PowerShell converts them to text to make them suitable for human consumption. PowerShell supports several options to help you control this formatting process, as listed in Table 1-15.
Custom Formatting Files
All the formatting defaults in PowerShell (for example, when you do not specify a formatting command, or when you do not specify formatting properties) are driven by the *.Format.Ps1Xml files in the installation directory.
To create your own formatting customizations, use these files as a
source of examples, but do not modify them directly. Instead, create a
new file and use the Update-FormatData
cmdlet to load your
customizations. The Update-FormatData
cmdlet applies your changes to the current instance of PowerShell. If
you wish to load them every time you launch PowerShell, call Update-FormatData
in your profile script. The
following command loads Format.custom.ps1xml from
the same directory as your profile:
$formatFile = Join-Path (Split-Path $profile) "Format. Custom.Ps1Xml" Update-FormatData -PrependPath $typesFile
Capturing Output
There are several ways to capture the output of commands in PowerShell, as listed in Table 1-16.
Command | Result |
| Stores the objects produced by the PowerShell command
into |
$variable = Command | Out-String | Stores the visual representation of the PowerShell
command into |
| Stores the (string) output of the native command into
|
| For most commands, stores the objects produced by the
PowerShell command into |
Command >
File | Redirects the visual representation of the PowerShell
(or standard output of a native command) into
|
Command >>
File | Redirects the visual representation of the PowerShell
(or standard output of a native command) into
|
Command 2>
File | Redirects the errors from the PowerShell or native
command into |
Command
File | Redirects stream number |
Command 2>>
File | Redirects the errors from the PowerShell or native
command into |
Command
File | Redirects stream number |
Command > File
2>&1 | Redirects both the error and standard output streams of the PowerShell or native command into |
Command >>
File
2>&1 | Redirects both the error and standard output streams
of the PowerShell or native command into
|
Common Customization Points
As useful as it is out of the box, PowerShell offers several avenues for customization and personalization.
Console Settings
The Windows PowerShell user interface offers several features to make your shell experience more efficient.
Adjust your window size
In the System menu (right-click the title bar at the top left of the console window), select Properties→Layout. The Window Size options let you control the actual window size (how big the window appears on screen), whereas the Screen Buffer Size options let you control the virtual window size (how much content the window can hold). If the screen buffer size is larger than the actual window size, the console window changes to include scrollbars. Increase the virtual window height to make PowerShell store more output from earlier in your session. If you launch PowerShell from the Start menu, PowerShell launches with some default modifications to the window size.
Make text selection easier
In the System menu, click Options→QuickEdit Mode. QuickEdit mode lets you use the mouse to efficiently copy and paste text into or out of your PowerShell console. By default, PowerShell launches with QuickEdit mode enabled.
Use hotkeys to operate the shell more efficiently
The Windows PowerShell console supports many hotkeys that help make operating the console more efficient, as shown in Table 1-17.
Hotkey | Meaning |
Windows key-r, and then type | Launch Windows PowerShell. |
Up arrow | Scan backward through your command history. |
Down arrow | Scan forward through your command history. |
Page Up | Display the first command in your command history. |
Page Down | Display the last command in your command history. |
Left arrow | Move cursor one character to the left on your command line. |
Right arrow | Move cursor one character to the right on your command line. If at the end of the line, inserts a character from the text of your last command at that position. |
Home | Move the cursor to the beginning of the command line. |
End | Move the cursor to the end of the command line. |
Ctrl-left arrow | Move the cursor one word to the left on your command line. |
Ctrl-right arrow | Move the cursor one word to the right on your command line. |
Alt-space, e, l | Scroll through the screen buffer. |
Alt-space, e, f | Search for text in the screen buffer. |
Alt-space, e, k | Select text to be copied from the screen buffer. |
Alt-space, e, p | Paste clipboard contents into the Windows PowerShell console. |
Alt-space, c | Close the Windows PowerShell console. |
Ctrl-c | Cancel the current operation. |
Ctrl-break | Forcibly close the Windows PowerShell window. |
Ctrl-home | Deletes characters from the beginning of the current command line up to (but not including) the current cursor position. |
Ctrl-end | Deletes characters from (and including) the current cursor position to the end of the current command line. |
F1 | Move cursor one character to the right on your command line. If at the end of the line, inserts a character from the text of your last command at that position. |
F2 | Creates a new command line by copying your last command line up to the character that you type. |
F3 | Complete the command line with content from your last command line, from the current cursor position to the end. |
F4 | Deletes characters from your cursor position up to (but not including) the character that you type. |
F5 | Scan backward through your command history. |
F7 | Interactively select a command from your command history. Use the arrow keys to scroll through the window that appears. Press the Enter key to execute the command, or use the right arrow key to place the text on your command line instead. |
F8 | Scan backward through your command history, only displaying matches for commands that match the text you’ve typed so far on the command line. |
F9 | Invoke a specific numbered command from your command history. The numbers of these commands correspond to the numbers that the command-history selection window (F7) shows. |
Alt-F7 | Clear the command history list. |
Note
While useful in their own right, the hotkeys listed in Table 1-17 become even more useful when you map them to shorter or more intuitive keystrokes using a hotkey program such as the free (AutoHotkey).
Profiles
Windows PowerShell automatically runs the four scripts listed in Table 1-18 during startup. Each, if present, lets you customize your execution environment. PowerShell runs anything you place in these files as though you had entered it manually at the command line.
Profile purpose | Profile location |
Customization of all PowerShell sessions, including PowerShell hosting applications for all users on the system | InstallationDirectory\profile.ps1 |
Customization of PowerShell.exe sessions for all users on the system | InstallationDirectory\ Microsoft. PowerShell _profile.ps1 |
Customization of all PowerShell sessions, including PowerShell hosting applications | <My Documents>\WindowsPowerShell\profile.ps1 |
Typical customization of PowerShell.exe sessions | <My Documents>\WindowsPowerShell\ Microsoft.PowerShell _profile.ps1 |
PowerShell makes editing your profile script simple by defining
the automatic variable $profile
. By
itself, it points to the “current user, PowerShell.exe” profile. In
addition, the $profile
variable
defines additional properties that point to the other profile locations:
PS > $profile | Format-List -Force AllUsersAllHosts : C:\Windows\System32\ WindowsPowerShell\v1.0\ profile.ps1 AllUsersCurrent- Host : C:\Windows\System32\ WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1 CurrentUserAll- Hosts : E:\Lee\WindowsPowerShell\profile. ps1 CurrentUser- CurrentHost : E:\Lee\WindowsPowerShell\ Microsoft.PowerShell_ profile.ps1
To create a new profile, type:
New-Item -Type file -Force $profile
To edit this profile, type:
notepad $profile
Prompts
To customize your prompt, add a prompt
function to your profile. This function
returns a string. For example:
function Prompt { "PS [$env:COMPUTERNAME] >" }
Tab Completion
You can define a TabExpansion2
function to customize the way that Windows PowerShell completes
properties, variables, parameters, and files when you press the Tab
key.
Your TabExpansion
function
overrides the one that PowerShell defines by default, though, so you may
want to use its definition as a starting point:
Get-Content function:\TabExpansion2
User Input
You can define a PSConsoleHostReadLine
function to customize
the way that the Windows PowerShell console host (not the ISE) reads
input from the user. This function is responsible for handling all of
the user’s keypresses, and finally returning the command that PowerShell
should invoke.
Command Resolution
You can intercept PowerShell’s command resolution behavior in
three places by assigning a script block to one or all of the PreCommandLookupAction
, PostCommandLookupAction
, or CommandNotFoundAction
properties of $executionContext.SessionState.InvokeCommand
.
PowerShell invokes the PreCommandLookupAction
after
the user types a command name, but before it has tried to resolve the command. It invokes
the PostCommandLookupAction
once it has resolved a
command, but before it executes the command. It invokes the CommandNotFoundAction
when a command is not found, but before it generates an
error message. Each script block receives two arguments: CommandName
and CommandLookupEventArgs
.
$executionContext.SessionState.InvokeCommand. CommandNotFoundAction = { param($CommandName, $CommandLookupEventArgs) (...) }
If
your script block assigns a script block to the CommandScriptBlock
property of the CommandLookupEventArgs
or assigns a CommandInfo
to the Command
property of the CommandLookupEventArgs
, PowerShell will use that script block or command,
respectively. If your script block sets the StopSearch
property to true
, PowerShell will do no further command resolution.
Get Windows PowerShell Pocket Reference, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.