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) while commands do not.
You will often want to control the way that Windows PowerShell interprets your statements, so Table A.1, “Windows PowerShell evaluation controls” lists the options available to you.
Table A.1. Windows PowerShell evaluation controls
Statement | Example | Explanation |
|---|---|---|
Precedence control:
| PS > 5 * (1 + 2) 15 PS > (dir).Count 2276
| Forces the evaluation of a command or expression, similar to the way that parentheses are used to force the order of evaluation in a mathematical expression. |
Expression subparse:
|
PS > "The answer is (2+2)"
The answer is (2+2)
PS > "The answer is $(2+2)"
The answer is 4
PS > $value = 10
PS > $result = $(
>> if($value -gt 0) { $true }
> else { $false }
>> )
>
PS > $result
True
| Forces the evaluation of a command or expression, similar to the way that parentheses are used to force the order of evaluation in a mathematical expression. However, a subparse is as powerful as a subprogram, and is required only when it contains logic or flow control statements. This statement is also used to expand dynamic information inside a string. |
List evaluation:
|
PS > "Hello".Length
5
PS > @("Hello").Length
1
PS > (Get-ChildItem).Count
12
PS > (Get-ChildItem *.txt).Count
PS > @(Get-ChildItem *.txt).Count
1
| Forces an expression to be evaluated as a list. If it is already a list, it will remain a list. If it is not, PowerShell temporarily treats it as one. |
DATA evaluation: |
PS > DATA { 1 + 1 }
2
PS > DATA { $myVariable = "Test" }
Assignment statements are not allowed in
restricted language mode or a Data section. | Evaluates the given script block in the context of the PowerShell data language. The data language supports only data-centric features of the PowerShell language. |
To create single-line comments, begin a line
with the # character. To create a block (or multi-line)
comment, surround the region with the characters <#
and #>.
# This is a regular comment
<# This is a block comment
$null = @"
function MyTest
{
"This should not be considered a function"
}
$myVariable = 10;
"@
Block comment ends
#>
# This is regular script againWindows PowerShell provides several ways to define and access variables, as summarized in Table A.2, “Windows PowerShell variable syntaxes”.
Table A.2. Windows PowerShell variable syntaxes
Syntax | Meaning |
|---|---|
| A simple variable name. The variable name must consist of alphanumeric characters. Variable names are not case sensitive. |
| An arbitrary variable name. The variable name must be surrounded by curly braces, but may contain any characters. Curly braces in the variable name must be escaped with a backtick (`). |
| Variable "Get and Set Content" syntax. This is similar to the arbitrary variable name syntax. If the name corresponds to a valid PowerShell path, you can get and set the content of the item at that location by reading and writing to the variable. |
| Strongly typed variable. Ensures that the variable may contain only data of the type you declare. PowerShell throws an error if it cannot coerce the data to this type when you assign it. |
| Gets or sets the variable at that
specific scope. Valid scope names are |
| Creates a new variable using the Variable Provider. |
| Gets the variable using the
Variable Provider or |
| Creates a variable using the
|
I'm guessing you want "${c:ilename.extension}" to actually be something like "${c:pathfilename.extension}"
Unlike some languages, PowerShell rounds (not
truncates) numbers when it converts them to the [int] data type:
PS > (3/2) 1.5 PS > [int] (3/2) 2
To have PowerShell truncate a number, see Chapter 6, Calculations and Math.
Boolean (true or false) variables are most
commonly initialized to their literal values of $true and $false. When it evaluates variables as part of a
Boolean expression (for example, an if
statement), though, PowerShell maps them to a suitable Boolean
representation, as listed in Table A.3, “Windows PowerShell Boolean interpretations”.
Table A.3. Windows PowerShell Boolean interpretations
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 |
Arrays with only a single member are a bit special, though. I think this should be mentioned somewhere (although I'm not sure how to explain it in a good but concise way).
Windows PowerShell offers several facilities for working with plain-text data.
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 occurs), 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:
“doublequoted” -> “double-quoted”
PS > "Hello ""There""!" Hello "There"! PS > 'Hello ''There''!' Hello 'There'!
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:
$output =
"Current script name is: $($myInvocation.MyCommand.Path)"$output
gets a value similar to Current script name
is c:\Test-Script.ps1.
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.
Windows PowerShell supports escape sequences inside strings, as listed in Table A.4, “Windows PowerShell escape sequences”.
Table A.4. Windows PowerShell escape sequences
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. |
Even though you have the "any other character" note, I think it's worth adding `$ and too.
PowerShell offers several options for interacting with numbers and numeric data.
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 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:
$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 name.
Since computer administrators rarely get the
chance to work with numbers in even powers of ten, PowerShell offers the
numeric constants of pb, tb,
gb, mb, and kb
to represent petabytes (1125899906842624), terabytes (1099511627776),
gigabytes (1073741824), megabytes (1048576), and kilobytes (1024),
respectively:
Strictly speaking, those are Pebibytes, Tebibytes, Gibibytes, Mebibytes and Kibibytes. But I think mentioning that would only create confusion among the readers ;-)
PS > $downloadTime = (1gb + 250mb) / 120kb PS > $downloadTime 10871.4666666667
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.
See the section called “Working with the .NET Framework” to learn more about using PowerShell to interact with the .NET Framework.
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:
@() should be formatted as code.
$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 the section called “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
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 the section called “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
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 one 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 array, in decreasing order. PowerShell does not wrap around (and therefore scans backward in this case) because both numbers in the range share the same sign.
You can combine several of the above statements 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.
You can use the array slicing syntax to create arrays, as well:
$myArray = ,0+2..3+0,0
Should this code snippet perhaps be inside the “Note” box? Or is that just an artifact of the HTML view here?
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 access or modify a specific element in an associative array, you may 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.
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.
Once you have defined your data, the next step is to work with it.
The arithmetic operators let you perform mathematical operations on your data, as shown in Table A.5, “Windows PowerShell arithmetic operators”.
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 called “Working with the .NET Framework” to learn more about using PowerShell to interact with the .NET Framework.
Table A.5. Windows PowerShell arithmetic operators
Operator | Meaning |
|---|---|
+ | The addition operator: When used with numbers, returns their sum. When used with strings, returns a new string created by appending the second string to the first. When used with arrays, returns a new array created by appending the second array to the first. When used with hashtables, returns a new hashtable created by merging the two hashtables. Since hashtable keys must be unique, PowerShell returns an error if the second hashtable includes any keys already defined in the first hashtable. When used with any other type, PowerShell
uses that type's addition operator ( |
- | The subtraction operator: When used with numbers, returns their difference. This operator does not apply to strings. This operator does not apply to arrays. This operator does not apply to hashtables. When used with any
other type, PowerShell uses that type's subtraction operator
( |
* | The multiplication operator: When used with numbers, returns their product. When used with strings
( When used with
arrays ( This operator does not apply to hashtables. When used with any other type, PowerShell
uses that type's multiplication operator ( |
/ | The division operator: When used with numbers, returns their quotient. This operator does not apply to strings. This operator does not apply to arrays. This operator does not apply to hashtables. When used with any other type, PowerShell
uses that type's multiplication operator |
% | The modulus operator: When used with numbers, returns the remainder of their division. This operator does not apply to strings. This operator does not apply to arrays. This operator does not apply to hashtables. When used with any other type, PowerShell
uses that type's multiplication operator ( |
+= -= *= /= %= | Assignment operators: These operators match the simple arithmetic
operators (+, -, *, /, and
|
These operators match the simple arithmetic operators (+, -, *, /, and %) but store the result in the variable %= on the left-hand side of the operator.
I think there is a “%=” too much in the sentence there :-)
The operators should be typeset in the font used for code examples.
The logical operators let you compare Boolean values, as shown in Table A.6, “Windows PowerShell logical operators”.
Table A.6. Windows PowerShell logical operators
Operator | Meaning |
|---|---|
| Logical AND:
Returns You can combine
several
PowerShell implements the |
| Logical OR:
Returns You can combine
several
PowerShell implements the |
| Logical Exclusive OR:
Returns Returns |
| Logical NOT: -not Returns |
The logical NOT could use two lines of examples:
-not $value
! $value
since both operators are valid.
The binary operators, listed in Table A.7, “Windows PowerShell binary operators”, let you apply the
Boolean logical operators bit by bit to the operator's arguments. When
comparing bits, a 1 represents $true,
while a 0 represents $false.
Table A.7. Windows PowerShell binary operators
Operator | Meaning |
|---|---|
| Binary AND:
Returns a number where bits are set to 1 if the bits of the left-hand and right-hand arguments at that position are both 1. All other bits are set to 0. For example: PS > $boolean1 = "110110110" PS > $boolean2 = "010010010" PS > $int1 = [Convert]::ToInt32($boolean1, 2) PS > $int2 = [Convert]::ToInt32($boolean2, 2) PS > $result = $int1 -band $int2 PS > [Convert]::ToString($result, 2) 10010010 |
| Binary OR:
Returns a number where bits are set to 1 if either of the bits of the left-hand and right-hand arguments at that position is 1. All other bits are set to 0. For example: PS > $boolean1 = "110110110" PS > $boolean2 = "010010010" PS > $int1 = [Convert]::ToInt32($boolean1, 2) PS > $int2 = [Convert]::ToInt32($boolean2, 2) PS > $result = $int1 -bor $int2 PS > [Convert]::ToString($result, 2) 110110110 |
| Binary Exclusive OR:
Returns a number where bits are set to 1 if either of the bits of the left-hand and right-hand arguments at that position is 1, but not if both are. All other bits are set to 0. For example: PS > $boolean1 = "110110110" PS > $boolean2 = "010010010" PS > $int1 = [Convert]::ToInt32($boolean1, 2) PS > $int2 = [Convert]::ToInt32($boolean2, 2) PS > $result = $int1 -bor $int2 PS > [Convert]::ToString($result, 2) 100100100 |
| Binary NOT: -bnot Returns a number where bits are set to 1 if the bit of the right-hand (and only) argument at that position is set to 1. All other bits are set to 0. For example: PS > $boolean1 = "110110110" PS > $int1 = [Convert]::ToInt32($boolean1, 2) PS > $result = -bnot $int1 PS > [Convert]::ToString($result, 2) 11111111111111111111111001001001 |
Should those variables really be named $boolean*? I think $binary* would be more appropriate, since the table is talking about binary operators, not boolean ones.
PowerShell supports several other simple operators, as listed in Table A.8, “Other Windows PowerShell operators”.
Table A.8. Other Windows PowerShell operators
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 Appendix B, Regular Expression Reference. |
| 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,000The 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 Appendix D, .NET String Formatting. |
| 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
Delimiter is
interpreted as a regular expression match.
"SimpleMatch, RegexMatch, CultureInvariant, IgnorePatternWhitespace, Multiline, Singleline, IgnoreCase , ExplicitCapture". 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")
abThe binary join operator:
Combines
the supplied items into a single string, using
PS > "a","b" -join ", " a, b |
After the list of split options comes a paragraph containing a comma-separated list of the very same options again:
"SimpleMatch, RegexMatch, CultureInvariant, IgnorePatternWhitespace, Multiline, Singleline, IgnoreCase , ExplicitCapture".
I think that shouldn't be there.
The PowerShell comparison operators, listed in
Table A.9, “Windows PowerShell comparison operators”, 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, while the –c prefix performs a case-sensitive
comparison.
Table A.9. Windows PowerShell comparison operators
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 $true
if 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 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 Target that match Regular Expression. The
For example: PS > "Hello World" -match "(.*) (.*)" True PS > $matches[1] Hello For more information on the details of regular expressions, see also Appendix B, Regular Expression Reference. |
| The negated match operator: Returns
The |
| The contains operator:
Returns |
| The negated contains operator: Returns
|
| The type operator:
Returns |
| The negated type operator: Returns
|
"-not-contains" should be "-notcontains"
Row -ne: “For all primitive types, returns $true if$leftValue and $rightValue are not equal.” -> “For all primitive types, returns $true if $leftValue and $rightValue are not equal.” (missing space before $leftValue)
Row -ne: “When used with arrays, returns all elements in $leftValue that are not equal to$rightValue.” -> “When used with arrays, returns all elements in $leftValue that are not equal to $rightValue.” (missing space before $rightValue)
Row -like: “Any character in the range of a-b” -> “Any character in the range of a–b” (ranges in written text are usually typeset with an en-dash)
Row -match: Maybe mention that the $Matches variable will not be set if the operator is used against an array.
Conditional statements in PowerShell let you change the flow of execution in your script.
if(condition){ statement block } elseif(condition){ statement block } else { statement block }
If condition
evaluates to $true, then 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.
See the section called “Simple Operators” and the section called “Comparison Operators” for a discussion on how PowerShell evaluates expressions as conditions.
If condition
evaluates to $false, then PowerShell
evaluates any following (optional) elseif conditions until one matches.
If one matches, PowerShell executes the statement block associated with
that condition, then resumes execution at the end of the if / elseif / else statement list.
“elseif” in the first sentence should be typeset as code.
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.
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.
“it evaluates expression against the statements in the switch body”
I think it evaluates the expression against the conditions in the switch body. Statements are usually things that are executed and not thing that are just compared against. The help text of about_Switch also uses “condition”.
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 A.10, “Options supported by PowerShell switch statements”.
Table A.10. Options supported by PowerShell switch statements
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 other tables above have put the description into a single table cell, instead of spreading it over two rows. Also, as seen with -not/! in the case of multiple options that do the same they also got collapsed into a single cell. This table here however breaks the long and short options in two individual rows; the description header and description text likewise are in two separate rows.
This probably isn't noticeable in print if the vertical alignment of table cell contents is at the top and rows cannot be distinguished. But here it is a little distracting and makes it look like -exact and -e are different options, since they are in different rows.
last row: “Any character in the range of a-b” -> “Any character in the range of a–b” (ranges in written text are usually typeset with an en-dash) (as mentioned above already; just in case this change is accepted and one instance would be forgotten :-))
The { comparison
expression } statements let you process the current input
item, which is stored in the $_
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.
A reference to how continue works in a switch statement is necessary, especially since PowerShell's switch statement works with a pipeline and is therefore different. A little more about break too. Break exits the switch and doesn't process any of the other items in the pipeline. Continue stops processing the current item immediately, but continues with the next.
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
See the section called “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 in PowerShell let you execute groups of statements multiple times.
: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.
Should it be mentioned that increment, condition and initialization can be omitted (though only starting from the right)? So all of the following are valid for statements:
for (initialization; condition; increment) { ... }
for (initialization; condition) { ... }
for (initialization) { ... }
for () { ... }
(Yes, the last one is essentially an endless loop.)
For example:
for($counter = 0; $counter -lt 10; $counter++)
{
Write-Host "Processing item $counter"
}The break
and continue statements can specify
the loop_label of any enclosing looping
statement as their target.
:loop_label foreach (variable in expression)
{
statement block
}The foreach discussion seems incomplete without covering:
expression | foreach {}
expression | % {}
expression | foreach { BEGIN{} PROCESS {$_} END{} }
foreach-object -Begin
Thanks, great feedback. I added a pointer to the larger "Repeat Operations with Loops" recipe, and added that to the recipe.
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
}
$handleSumThe break
and continue statements (discussed
later in the chapter) 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. For more information, see the section called “Repeat Operations with Loops”.
:loop_labelwhile(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 can specify
the loop_label of any enclosing looping
statement as their target.
:loop_labeldo { statement block } while(condition)
or
:loop_labeldo { 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 can specify
the loop_label of any enclosing looping
statement as their target.
PowerShell supports two statements to help you
control flow within loops: break and
continue.
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 example, break :outer_loop" -> "for example, break outer_loop" (the colon is not part of the loop's name. No error will be raised, but the break would function as if no loop name was given.)
The example below uses just outer as the loop name, as does the description and the example of continue, while this description uses outer_loop. I suggest that all instances of an example outer loop name should be the same, either outer_loop or outer.
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
Now I'm a little confused. If break :outer would really break the outer loop, then the output should be
Processing item 0,0
Processing item 0,1
and nothing else. As soon as $counter2 reaches 2 the complete outer loop stops.
The output is what I get with your code; however it's the same when I use just break which tells me that break :outer only breaks the inner loop.
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"
}
}Found the mistake (see below comment at the output):
It should be break outer. The colon introduces a name for a loop but it's not part of said name. Therefore
break outer
will break the loop that began with
:outer for (...)
Produces the output:
Processing item 0,0 Processing item 0,1
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:
Same here as with break: The colon is not part of the loop's name, therefore it must read
continue outer
instead of
continue :outer
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"
}
}Same here again:
continue :outer
needs to be
continue outer
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
With above change the output changes to:
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
Thanks, I don't know how I missed those!
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
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.
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 IdleTo 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.
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 rare, some types let you set the value of some static 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.
The two primary avenues for learning about
classes and types are the Get-Member
cmdlet and the documentation for the .NET Framework.
To learn what methods and properties a given
type supports, pass it through the Get-Member cmdlet, as shown in Table A.11, “Working with the Get-Member cmdlet”.
Table A.11. Working with the Get-Member cmdlet
Action | Result |
|---|---|
| All the static methods and properties of a given type |
| All the static methods and
properties provided by the type in
|
| All the instance methods and
properties provided by the type in
Get-Member -InputObject $objectReference |
| All the instance methods and
properties of a |
second to last row: “use the–InputObject parameter of Get-Member” -> “use the -InputObject parameter of Get-Member”:
-InputObject
-InputObject and Get-Member should be typeset as code
-InputObject should start with U+002D Hyphen-Minus, not with U+2013 En Dash)
Another source of information about the classes in the .NET Framework is the documentation itself, available through the search facilities at http://msdn.microsoft.com.
Typical documentation for a class first starts with a general overview, then provides a hyperlink to the members of the class—the list of methods and properties it supports.
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 membersThe 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.
When you specify a type name, PowerShell lets you use a short form for some of the most common types, as listed in Table A.12, “PowerShell type shortcuts”.
Table A.12. PowerShell type shortcuts
Type shortcut | Full classname |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$objectReference = New-Object TypeName 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 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.comPowerShell 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 Appendix H, Selected COM Objects and Their Uses.
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 lets you dynamically add
methods, properties, and more to an object. It supports the extensions
shown in Table A.13, “Selected member types supported by the Add-Member
cmdlet”.
Table A.13. Selected member types supported by the Add-Member cmdlet
Member type | Meaning |
|---|---|
| A property defined to alias another property: PS > $testObject = [PsObject] "Test" PS > $testObject | Add-Member "AliasProperty" Count Length PS > $testObject.Count 4 |
| A property defined by a
This method must be public, static, return
results (nonvoid), and take one parameter of type |
| A property defined by the initial value you provide: PS > $testObject = [PsObject] "Test" PS > $testObject | Add-Member NoteProperty Reversed tseT PS > $testObject.Reversed tseT |
| A property defined by the
script block you provide. In that script block, PS > $testObject = [PsObject] ("Hi" * 100)
PS > $testObject | Add-Member ScriptProperty IsLong {
>> $this.Length -gt 100
>> }
>> $testObject.IsLong
>>
True |
| A property defined as a
shortcut to a set of properties. Used in cmdlets such as
PS > $testObject = [PsObject] [DateTime]::Now
PS > $collection = New-Object `
>> Collections.ObjectModel.Collection``1[System.String]
>> $collection.Add("Month")
>> $collection.Add("Year")
>> $testObject | Add-Member PropertySet MonthYear $collection
>> $testObject | select MonthYear
>>
Month Year
----- ----
3 2010 |
| A method defined by a
This method must be public, static, and
take one parameter of type |
| A method defined by the
script block you provide. In that script block, PS > $testObject = [PsObject] "Hello"
PS > $testObject | Add-Member ScriptMethod IsLong {
>> $this.Length -gt $args[0]
>> }
>> $testObject.IsLong(3)
>> $testObject.IsLong(100)
>>
True
False |
second row: “A property defined by a: System.Reflection.MethodInfo.” -> “A property defined by a System.Reflection.MethodInfo.” (superfluous colon)
Row PropertySet: I get the properties returned in the order of Month,Year instead of Year,Month. Furthermore the column alignment is a little off (the numbers should be right-aligned). Also Year should be underlined by four dashes, not six.
Row CodeMethod: “A method defined by a: System.Reflection.MethodInfo.” -> “A method defined by a System.Reflection.MethodInfo.” (superfluous colon)
On that note: Should the description for CodeProperty also refer to System.Reflection.MethodInfo? I know properties are internally just method calls and metadata, but maybe there's also a typo here.
Re: CodeProperty. It is indeed a method - thanks for keeping your eyes sharp!
PS > $item = Get-Item c: PS > [Microsoft.PowerShell.Commands.FileSystemProvider]::Mode($item) d--hs
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
For more information about custom type extensions files, see the section called “Add Custom Methods and Properties to Types”.
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 used 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.
To write a script, write your PowerShell commands in a text editor and save the file with a .ps1 extension.
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.
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
the section called “Cmdlet keywords in commands”.
There needs to be some discussion preceding this that explains the optional BEGIN, PROCESS and END keywords work in a Function, otherwise there's no context to understand how Filter is different.
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$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 may
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.
There are two ways to execute a command (script, function, or script block): by invoking it or by dot-sourcing it.
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.
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 ...& Invoke-MyFunctionparameter1 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 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 ParametersBy 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 RemoteSignedIf 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
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 @parametersPowerShell offers several options for processing input to a command.
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
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 only to type
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.
The elements of the
[CmdletBinding()] attribute describe how your
script or function interacts with the system.
$trueIf $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.
nameDefines 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.
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, and High.
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 is Medium.
The elements of the
[Parameter()] attribute mainly define how your
parameter behaves in relation to other parameters. All elements are
optional.
The list below doesn't format “$true” as code, while the list above does. Also I don't quite see why only the part after the equals sign would be considered code; in a way each attribute element including its value is code.
Ok, I begin to see the reasoning of the formatting; the code-formatted parts are values which may be provided with a different value. Still, “$true” below should then be formatted as code as well :-)
Defines the parameter as mandatory. If the user doesn't supply a value to this parameter, PowerShell automatically prompts them for it. When not specified, the parameter is optional.
positionDefines the position of this
parameter. This applies when the user provides parameter values
without specifying the parameter they apply to (i.e.
Argument2 in:
Invoke-MyFunction -.) PowerShell
supplies these values to parameters that have defined a
Position, from lowest to highest. When not
specified, the name of this parameter must be supplied by the
user.Param1
Argument1
Argument2
nameDefines 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 parameter sets that it is
defined in. This feature is used, for example, when the user may
only supply 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.
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.
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.
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.
In addition to the
[Parameter()] attribute, PowerShell lets you apply
other attributes that add additional behavior or validation
constraints to your parameters. All validation attributes are
optional.
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 only be refered to by the name you originally declared.
Allows this parameter to receive
$null as its value. This is only required for
mandatory parameters. When not specified, mandatory parameters
can not receive $null as their value,
although optional parameters can.
Allows this string parameter to receive an empty string as its value. This is only required for mandatory parameters. When not specified, mandatory string parameters can not 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.
Allows this collection parameter to receive an empty collection as its value. This is only required for mandatory parameters. When not specified, mandatory collection parameters can not 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.
lower limit,
upper limit)]Restricts the number of elements that may 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.
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.
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.
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.
{ 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
$_ variable, and then invokes your script
block. If the script block returns $true (or
anything that can be converted to $true—such
as non-empty strings), PowerShell considers the validation to
have been successful.
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 non-standard rules (such as
case-sensitive comparison of strings), you can instead write the
validation in the body of the script or function.
Ensures that input supplied to this
parameter is not null. This is the default behavior of mandatory
parameters, and is useful only for optional parameters. When
applied to string parameters, a $null
parameter value gets instead converted to an empty
string.
Ensures that input supplied to this
parameter is not null or empty. This is the default behavior of
mandatory parameters, and 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.
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)
When pipeline input is a core scenario of
your command, you may 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 $_ 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.
The $MyInvocation automatic variable contains
information about the context under which the script was run,
including detailed information about the command
(MyCommand), the script that defines it
(ScriptName), and more.
Can text be formatted as code in headers?
PowerShell provides three primary ways to retrieve output from a command.
any commandThe return value/output of a script is any data that it generates, but does not capture. If a command contains the commands:
"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 valueThe statement
return $false
is simply a short form for pipeline output:
$false return
exit errorlevelThe exit
statement returns an error code from the current command or instance
of PowerShell. If called in 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.
“that sets the $? automatic variable” → “that sets the $? automatic variable” (formatting $? as code)
Type Get-Help
about_automatic_variables for more information about
automatic variables.
PowerShell automatically generates help content out of specially-tagged comments in your command:
<# .SYNOPSIS Runs a ... .EXAMPLE PS > ... #> param( $param1 )
Help-specific comments must be the only comments in a comment block. If PowerShell discovers a non-help comment, it discontinues looking for comments in that comment block. If you need to include non-help 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:
A short summary of the command, ideally a single sentence.
A more detailed description of the command.
nameA description of parameter
name, with one for each parameter you
want to provide a description. 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.
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.
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.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.Any additional notes or remarks about this command.
A link to a related help topic or
command, with one .LINK tag per link. If the
related help topic is an URL, PowerShell launches that URL when
the user supplies the -Online parameter to
Get-Help for your command.
PowerShell supports two classes of errors:
nonterminating and terminating.
It collects both types of errors as a list in the $error automatic variable.
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, as shown in Table A.14, “ErrorActionPreference automatic variable values”.
Table A.14. ErrorActionPreference automatic variable values
Value | Meaning |
|---|---|
| Do not display errors. |
| 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 the above values to its ErrorAction parameter.
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 messageIn 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, while 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 exeptions 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.
If specified, the continue keyword tells PowerShell to continue
processing the rest of 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. Break is the default mode, and applies if you
specify neither break nor continue at all.
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 A.15, “PowerShell formatting commands”.
Table A.15. PowerShell formatting commands
Formatting command | Result |
|---|---|
| Formats the properties of the input objects as a table, including only the object properties you specify. If you do not specify a property list, PowerShell picks a default set. In addition to supplying object properties, you may also provide advanced formatting statements: PS > Get-Process | `
Format-Table -Auto Name,`
@{Label="HexId";
Expression={ "{0:x}" -f $_.Id}
Width=4
Align="Right"
}The advanced formatting
statement is a hashtable with the keys For more information about the |
| Formats the properties of the input objects as a list, including only the object properties you specify. If you do not specify a property list, PowerShell picks a default set. The The The command
For more information
about the |
| Formats the properties of the input objects in an extremely terse summary view. If you do not specify a property, PowerShell picks a default. In addition to supplying object properties, you may also provide advanced formatting statements: PS > Get-Process | `
Format-Wide -Auto `
@{ Expression={ "{0:x}" -f $_.Id} }The advanced formatting statement is a
hashtable with the key For more information
about the |
Row Format-Table: “represented by the $_ variable” → “represented by the $_ variable” (“variable” shouldn't be formatted as code)
Row Format-List: “does not include thosethat PowerShell hides” → “does not include those that PowerShell hides” (missing space between “those” and “that”)
Row Format-Wide: “represented by the $_variable” → “represented by the $_ variable” (formatting $_ as code and missing space between $_ and “variable”)
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 in a manner similar to the type extension files mentioned in the section called “Add Custom Methods and Properties to Types”.
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
There are several ways to capture the output of commands in PowerShell, as listed in Table A.16, “Capturing output in PowerShell”.
Table A.16. Capturing output in PowerShell
Command | Result |
|---|---|
| Stores the objects produced by
the PowerShell command into
|
| 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
|
| Redirects the visual
representation of the PowerShell (or standard output of a native
command) into |
| Redirects the visual
representation of the PowerShell (or standard output of a native
command) into |
| Redirects the errors from the
PowerShell or native command into |
| Redirects the errors from the
PowerShell or native command into |
| Redirects both the error and
standard output streams of the PowerShell or native command into
|
| Redirects both the error and
standard output streams of the PowerShell or native command into
|
First column: Spaces (often) and in one instance the | character are not formatted as code. This looks a bit weird when the spaces in two commands directly adjacent are of differing length.
As useful as it is out of the box, PowerShell offers several avenues for customization and personalization.
The Windows PowerShell user interface offers several features to make your shell experience more efficient.
In the System menu (right-click the PowerShell icon 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), while 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.
The system menu is accessed by either left-clicking the window's icon or by right-clicking the title bar. Right-clicking the icon is merely a side-effect of right-clicking the title bar :-)
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. If you launch PowerShell from the Start menu, PowerShell launches with QuickEdit mode enabled.
The Windows PowerShell console supports many hotkeys that help make operating the console more efficient, as shown in Table A.17, “Windows PowerShell hotkeys”.
Table A.17. Windows PowerShell hotkeys
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. |
Control + left arrow | Move the cursor one word to the left on your command line. |
Control + 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. |
Control + c | Cancel the current operation. |
Control + break | Forcefully close the Windows PowerShell window. |
Control + home | Deletes characters from the beginning of the current command line up to (but not including) the current cursor position. |
Control + 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. |
While useful in their own right, the hotkeys listed in Table A.17, “Windows PowerShell hotkeys” become even more useful when you map them to shorter or more intuitive keystrokes using a hotkey program such as the free AutoHotkey http://www.autohotkey.com.
Windows PowerShell automatically runs the four scripts listed in Table A.18, “Windows PowerShell profiles” 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.
Win 7 uses DocumentsWindowsPowerShell instead of My Documents
Table A.18. Windows PowerShell profiles
Profile purpose | Profile location |
|---|---|
Customization of all PowerShell sessions, including PowerShell hosting applications for all users on the system |
|
Customization of PowerShell.exe sessions for all users on the system |
|
Customization of all PowerShell sessions, including PowerShell hosting applications |
|
Typical customization of PowerShell.exe sessions |
|
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\profil
e.ps1
AllUsersCurrentHost : C:\Windows\System32\WindowsPowerShell\v1.0\Micros
oft.PowerShell_profile.ps1
CurrentUserAllHosts : E:\Lee\WindowsPowerShell\profile.ps1
CurrentUserCurrentHost : E:\Lee\WindowsPowerShell\Microsoft.PowerShell_pro
file.ps1To create a new profile, type:
New-Item -Type file -Force $profile
To edit this profile, type:
notepad $profile
To customize your prompt, add a prompt function to your profile. This function
returns a string. For example:
function Prompt
{
"PS [$env:COMPUTERNAME] >"
}For more information about customizing your prompt, see also the section called “Customize Your Shell, Profile, and Prompt”.
You may define a TabExpansion 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:\TabExpansion
As its arguments, this function receives the entire command line as input, as well as the last word of the command line. If the function returns one or more strings, PowerShell cycles through those strings during tab completion. Otherwise, it uses its built-in logic to tab-complete file names, directory names, cmdlet names, and variable names.
No comments yet
Add a comment