Lab Manual Windows PowerShell Scripting
Lab Manual Windows PowerShell Scripting
Page i
Information in this document is subject to change without notice. The example companies, organizations,
products, people, and events depicted herein are fictitious. No association with any real company, organization,
product, person or event is intended or should be inferred. Complying with all applicable copyright laws is the
responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced,
stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical,
photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft
Corporation.
Microsoft may have patents, patent applications, trademarked, copyrights, or other intellectual property rights
covering subject matter in this document. Except as expressly provided in any written license agreement from
Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights,
or other intellectual property.
2006 Microsoft Corporation. All rights reserved.
Microsoft, MS-DOS, MS, Windows, Windows NT, MSDN, Active Directory, BizTalk, SQL Server, SharePoint,
Outlook, PowerPoint, FrontPage, Visual Basic, Visual C++, Visual J++, Visual InterDev, Visual SourceSafe,
Visual C#, Visual J#, and Visual Studio are either registered trademarks or trademarks of Microsoft Corporation
in the U.S.A. and/or other countries.
Other product and company names herein may be the trademarks of their respective owners.
Page ii
Contents
LAB 1: MONAD SCRIPTING.....................................................................................................................................1
Lab Objective .........................................................................................................................................................1
Exercise 1 Use Simple Shell Commands............................................................................................................1
Task 1 Running Commands ...........................................................................................................................1
Task 2 Running Cmdlets.................................................................................................................................2
Task 3 Running Cmdlets Safely .....................................................................................................................3
Task 4 Getting Help ........................................................................................................................................3
Task 5 Create Aliases.....................................................................................................................................4
Exercise 2 Expressions .......................................................................................................................................4
Task 1 Create an Expression..........................................................................................................................4
Task 2 Assignment .........................................................................................................................................5
Exercise 3 Using Pipelines..................................................................................................................................6
Task 1 Understand how the filter Cmdlets work .............................................................................................6
Task 2 Using Cmdlets to discover information about what other Cmdlets produce .......................................7
Task 3 Using the filter Cmdlets to manipulate a dataset ................................................................................7
Task 1 Use the filter Cmdlets to create more complex operations .................................................................7
Exercise 4 Branching Statements .......................................................................................................................8
Task 1 If/ElseIF/Else .......................................................................................................................................8
Task 2 Switch..................................................................................................................................................9
Exercise 5 Looping............................................................................................................................................10
Task 1 Understanding the WHILE statement ...............................................................................................10
Task 2 Understanding the "DO WHILE" statement ......................................................................................10
Task 3 Understanding the "DO UNTIL" statement .......................................................................................10
Task 4 Understanding the FOREACH statement .........................................................................................11
Task 5 Understanding the FOR statement ...................................................................................................11
Exercise 6 Handling Errors ...............................................................................................................................11
Task 1 Retrieve Errors ..................................................................................................................................12
Task 2 Recognizing terminating and non-terminating errors........................................................................12
Task 3 Using Trap.........................................................................................................................................13
Exercise 7 Formatting Output ...........................................................................................................................13
Task 1 Selecting your format look ................................................................................................................14
Task 2 Modifying the formatting....................................................................................................................14
Exercise 8 Creating Functions and Scripts .......................................................................................................14
Task 1 Declaring Function Names................................................................................................................14
Task 2 Declaring Parameters and Dealing with Arguments .........................................................................15
Task 3 Functions and Input...........................................................................................................................15
Task 4 Scripts ...............................................................................................................................................15
Exercise 9 Solving Problems ............................................................................................................................16
Task 1 Write a function .................................................................................................................................16
Task 2 Write a function .................................................................................................................................16
Task 3 Write a filter .......................................................................................................................................16
SOLUTIONS.............................................................................................................................................................18
Task 1...................................................................................................................................................................18
Task 2...................................................................................................................................................................18
Task 3...................................................................................................................................................................18
Page iii
Lab Objective
Estimated time to complete this lab: 90 minutes
The following tasks should help gain familiarity with the Monad shell.
Use Expressions
Create functions
Create scripts
In this exercise, you will learn how to start the shell and run commands as well as how to get help about
the various commands and topics about the shell. You will also discover the differences between
stand-alone and built-in commands and how to create aliases to reduce the amount of typing that is
needed. You will be using one of the two modes of the shell "Command Mode"; the other mode,
"Expression Mode", will be discussed in Exercise 2.
Task 1 Running Commands
Running commands in the Monad shell is the same as other shells.
This task shows that the new shell is very similar to CMD.EXE - you type commands and execute
programs. It is important to note that you are not running any built-in commands (such as DIR or
COPY, etc) in this first task.
1. Start the shell
Page 1
3.
Run some simple commands, note that you should see the default shell prompt "MSH> " in the
new console window. Also note that we are running stand-alone applications.
MSH> ipconfig
MSH> notepad
MSH> net statistics workstation
Note that the output for those commands is seen in the console window and that for graphical
commands, the prompt returns right away. Also note that arguments are provided to the commands
without special handling; for example, no quoting is needed to provide the string parameter values.
When executing commands, the shell is in Command Mode, this means that generally quoting is not
needed for arguments to commands.
More than one command (or Cmdlet) can be run on the same line. The ";" indicates that the statement
is finished.
4. Run ipconfig followed by net statistics workstation on the same line
MSH> ipconfig; net statistics workstation
Note the format of these commands, all in the form of get-something. The shell has a large number
of built-in commands (more than 120). Another cmdlet is provided to show you the list of Cmdlets.
3.
You will see that the list of Cmdlets is alphabetized by name, this will aid in locating the Cmdlet that
you want. The Get-Command Cmdlet has parameters. A parameter is a way to provide more
information to a command to get different or more specific information. By providing a parameter
to the get-command Cmdlet, it is possible to get more information about a command
4.
You will see that the output is no longer a list of Cmdlets but the synopsis of how to use the Cmdlet.
This can be useful when determining which parameters are available to the Cmdlet.
Page 2
See what would happen if you were to stop the processes of the system that match MSH
MSH> get-process msh*
MSH> stop-process -id 1124 -whatif
(using the Process ID number retrieved by get-process) You should see output similar to
What if: Performing operation "stop-process" on Target "msh (1124)".
This tells you what would have happened if the Cmdlet had executed normally. It should be noted
that not all Cmdlets support the -whatif parameter. This functionality must be implemented by the
Cmdlet developer. Our guidance to developers is that if a Cmdlet changes the state of the system,
they should support -whatif. However, individual Cmdlets may vary in implementation.
2. Get the processes of the system that match MSH and use -confirm to ensure that an operation
does not take place unless the action is confirmed.
MSH> get-process msh*
Use -confirm to have the shell inquire whether the process should be stopped.
MSH> stop-process -id 1124 -confirm
[?] Help
Get the processes of the system that match notepad and use -verbose to get detailed information
about what the Cmdlet is doing. First, start notepad
MSH> notepad
Use "-verbose" to have the shell report on what applications are stopped.
MSH> get-process notepad
MSH> stop-process -id 5772 -verbose
This will display the introduction to the shell help system. Review this material, note that some
topics may not be available in this pre-release.
2. Get help about the Get-Help Cmdlet
MSH> get-help get-help
3.
Where there are examples in the help output, run those examples to further discover the shell
environment.
4.
Page 3
Use an alias
MSH> gps
It is important to note that aliases are simple "nicknames" for Cmdlets. It is not possible to create an
alias for a Cmdlet and parameters. That will be done with functions in a later exercise.
Exercise 2 Expressions
Proctor Note: Introduce expressions and clarify the difference between Expression and Command
mode.
In this exercise, you will use expressions and discover the difference between Expression mode and
Command mode
Task 1 Create an Expression
With Monad an expression is created when it does not result in the execution of a Cmdlet or other
executable. For example, If an unquoted string is typed at the prompt, the shell will attempt to find an
executable using the string as a name, if the shell cannot find an executable, an error is returned.
However, if a quoted string is typed at the prompt, the shell's expression mode is entered and the shell
will echo back the quoted string as an expression.
1. Type an expression in the form of a quoted string
MSH> "Hello World"
Hello World
Note that the string 'Hello World' is echoed back to the user. Strings, when found as the first
element in a command place the shell in expression mode and any result from the expression will
result in a string.
2.
Note that in the Monad shell, it is possible to create strings by using the "+" operator. This allows
strings to be created very easily. It is also possible to create strings via multiplication. The
multiplication of strings requires that a string, followed by "*", followed by a number is present.
3. Create a string of "#"'s that is 65 characters long.
MSH> "#" * 65
Page 4
#################################################################
4.
Expression mode is also entered when a number is the first element of a command. This lets the
shell act like a calculator
MSH> 2 + 3 * 4 / 5
4.4
Note the precedence in this operation is first multiplication and division, reading left to right
followed by addition and subtraction, reading left to right. The following is what the explicit
precedence would be in the above example:
MSH> 2 + ((3 * 4)/5) - 6
-1.6
Task 2 Assignment
An assignment expression has two parts, the left hand side (LHS) of the "=" and the right hand side
(RHS). The LHS will be the storage of the results of the RHS, this storage is a variable, is generally a
string and must begin with a "$". The RHS may be an expression (such as a string, or arithmetic
expression), or it may be a command.
1. Create a Variable named Var with the value 2
MSH> $var = 2
Note that the RHS is an expression, not a command. In order to see the value of the variable, you
only need to refer to it, no extra command is necessary to echo it to the screen.
2. See the contents of the variable
MSH> $var
2
3.
It is also possible to store the results of a command execution in a variable. Try storing the
results of the Get-Date Cmdlet to the variable date
MSH> $date = Get-Date
Note, in this case, the RHS is a command - this is an expression where the RHS is in Command
Mode. Now, retrieve the contents of the variable
MSH> $date
Friday, August 19, 2005 11:06:54 AM
It is possible to store more than a single value in a variable. Variables can be arrays of values. The
following shows how to create an array of 4 numbers and assign it to a variable and then retrieve
the contents of the variable
MSH> $arr = 1,2,3,4
MSH> $arr
1
2
3
4
Note that the array is shown over 4 lines, since there are 4 elements in the array; each element
gets its own line of output. Many Cmdlets return more than one result. These results can be stored
in a variable in the same way as single results.
You can also force an array to be created. Using the array operator @( ) ensures that the contents
between the ( ) will be treated as an array. The following forces an array of 1 element to be
created:
MSH> $arr = @( "Hello There" )
Page 5
4.
Associative arrays (also called hash tables) may be created in the Monad shell. The general
syntax for creating a hash table is:
$hash = @{ key1 = value; key2 = value }
where value is an expression that returns a value (so this could be a number, string, or pipeline).
To refer to the values of a hash table, you can use the following syntax:
$hash["key1"] or $hash.key1.
Create a hash table with three keys, the value of the first is the number 1, the value of the second is
the string "two" and the value of the third the result of the get-date Cmdlet. Then retrieve the value
of the third key.
MSH> $hash = @{ key1 = 1; key2 = "two"; key3 = get-date }
MSH> $hash.key3
5.
The variable "$Processes" now contains the results of the Get-Process Cmdlet. This is an array of
Process Objects. These objects can now be retrieved.
It is very important to note that the variable contains the objects rather than a text representation of
the objects. Later we will see how important this is.
6.
Since this variable is an array, it is possible to use the shell's array notation to retrieve elements
from the variable. Run Get-Help about_array for more details.
2.
Inspect the help for the Where-Object Cmdlet, specifically reviewing the about_script_block help.
It is important to remember that $_ is a variable that represents the current pipeline object. We
will use this a great deal when using where-object.
MSH> get-help Where-Object
MSH> get-help about_script_block
3.
Inspect the help for the Foreach-Object Cmdlet. It is important to remember that $_ is a variable
that represents the current pipeline object. We will use this a great deal when using foreachobject.
4.
5.
Task 2 Using Cmdlets to discover information about what other Cmdlets produce
One of the most important Cmdlets is the Get-Member Cmdlet. This Cmdlet allows you to discover
things about the objects that are retrieved by the system. It is one of the most important tools of
discovery in the shell. You generally use this Cmdlet by piping the results of one Cmdlet to it.
1. Use the Get-Member Cmdlet to discover what types of objects the get-process Cmdlet returns
MSH> get-process | get-member
2.
You should be able to see that the previous pipeline retrieved information about the objects
returned by get-process. You can also get information about the elements of those objects.
Using the Get-Member Cmdlet in combination with Foreach-Object, we can discover more about
the process object.
3.
In some cases, a Cmdlet may return more than one type of object. In these cases, the getmember Cmdlet will return information for each of the types that it receives.
Use the Where-Object Cmdlet to retrieve only those files that have a size larger than 1 megabyte
in the Windows\System32 directory
3.
For each object that is returned by the Get-Drive Cmdlet, only print the name of the drive
4.
Select the top 10 processes based on VirtualMemorySize (This uses both sort-object and selectobject)
-type cmdlet
|
$_.parametersets } |
$_.parameters }
|
$_.name }
|
Page 7
#
#
#
#
line
line
line
line
1
2
3
4
sort-object |
group-object |
sort-object count
# line 5
# line 6
# line 7
In this exercise, you will use the various branching functionality of the shell.
Task 1 If/ElseIF/Else
You can use the IF statement to run a code blocks if a specified conditional test evaluates to true. You
can also specify one or more additional conditional tests to run if all prior tests evaluate to false. Finally,
you can specify an additional code block that is run if no other prior conditional test evaluates to true.
The following shows the IF statement syntax:
if (<test1>)
{<code_block1>}
[elseif (<test2)
{<code_block2>}]
[else
<code_block3>}]
1.
The comparison operators are used a great deal in branch logic, you should review the help for
comparison operators by reviewing the help on about_comparison_operators
MSH> get-help about_comparison_operators
2.
3.
4.
Create an IF/ELSEIF/ELSE statement that first checks if $a is 0 and if so emit "0", then $a -eq 1
and if so, emit "1", otherwise emit "other"
Page 8
While you can use multiple elseif statements to chain a series of conditional tests, each of which is
examined only if all the previous tests are false. However, if you need to create an if statement
containing many elseif statements within it, consider using a switch statement instead.
Task 2 Switch
The switch statement is a control statement that handles multiple selections by passing control to one
of the conditional statements within its body. Each conditional statement must be matched with a
statement block that will be executed if the conditional statement is met. The switch conditional has
following form:
switch [-regex|-wildcard|-exact][-casesensitive][-file filename | ( <pipeline> ) ]
{
[default|string|number|variable|{ conditional expression } { statementblock }]*
}
By default, if no options are used, switch behaves as if a case insensitive exact match is in effect. If
"pipeline" results in an array, each element of the array is evaluated in order. At least one conditional
element must be present and only one default clause may be present. If more than one "default"
clause is present, an error will result.
Examples:
MSH> $a = 3
MSH> switch ($a) {
1 {"got one"}
2 {"got two"}
3 {"got three"}
}
got three
In some cases, the special variable $_ is available in the script. $_ is an automatic variable that
represents the current value being evaluated.
MSH> $var = "word2"
MSH> switch -regex ($var) {
"word2" { "Exact " + $_ ; break }
"word.*" { "Pattern match Exact1 " + $_ ; break }
"w.*"{ "Pattern match first letter " + $_ ; break }
default { "Default " + $_; break }
}
Exact word2
In the following example, the omission of the break keyword allows for multiple matches.
MSH> $var = "word1","word2","word3"
MSH> switch -regex ($var) {
"word1" {"Multi-match Exact " + $_ }
"word2" {"Multi-match Exact " + $_ }
"w.*2"
{"Pattern match Exact " + $_ }
default {"Multi-match Default " + $_ }
}
Multi-match Exact word1
Multi-match Exact word2
Pattern match Exact word2
Multi-match Default word3
The following example uses script blocks to determine whether a match is made and the omission of
the break keyword allows for multiple matches.
Page 9
You should also review the help on about_break and about_continue which are generally used in
switch statements.
Exercise 5 Looping
MSH provides five looping statements; while, do while, do until, foreach and for.
Task 1 Understanding the WHILE statement
The WHILE statement (also known as a while loop) is a language construct for creating a loop that
runs commands in a script block as long as a conditional test evaluates to true. The "WHILE" statement
is easier to construct than a "FOR" statement because it's syntax is less complicated. In addition, it's
more flexible than the FOREACH statement because you specify a conditional test in the while
statement to control how many times the loop runs.
The following shows the while statement syntax:
while (<condition>){<script_block>}
1.
2.
What happens if the loop is run again? (without resetting the $i variable)
This is because the evaluation for truth occurs at the end of the loop rather than at the beginning
(as in the WHILE statement)
Task 3 Understanding the "DO UNTIL" statement
The "DO UNTIL" statement is similar to the WHILE except that the condition is checked at the end of
the command and it repeats until the condition is true.
Page 10
What happens if the loop is run again? (without resetting the $i variable)
MSH> do { $i; $i++ } until ($i -eq 11)
11
12
This is because the evaluation for truth occurs at the end of the loop rather than at the beginning
(as in the WHILE statement) and since $i is now not equal to 11 and never will be, it will continue
until you press Ctl-C.
Task 4 Understanding the FOREACH statement
The FOREACH statement (also known as a FOREACH loop) is a language construct for stepping
through (iterating) a series of values in a collection of items.
The simplest and most typical type of collection to traverse is an array. Within a foreach loop it's
common to run one or more commands against each item in an array.
The following shows the foreach syntax:
foreach ($<item> in $<collection>){<script_block>}
1. You should start this task by reviewing the help page for about_foreach
MSH> get-help about_foreach
2.
After reviewing the help create a FOREACH loop that echoes the numbers 1 through 10
3.
Create a FOREACH loop that echoes only the name of every file in the current directory
After reviewing the help create a for loop that counts from 0 to 10
3.
Page 11
Retrieve the error information from the $ERROR array variable. This array variable is an
inverted stack where the most recent errors are the lowest offset, so the last error that occurred is
$ERROR[0].
MSH> $error[0]
Attempted to divide by zero.
At line:1 char:4
+ 1 / <<<< $null
3.
Note that even though there was an error (when 1/0 was executed), the loop continued.
2. Execute a foreach loop that causes a dividebyzero error but does not report it
MSH> $ErrorActionPreference = "SilentlyContinue"
MSH> foreach ( $n in 2,1,0,1,2 ) { 1 / $n }
3.
Execute a foreach loop that causes a dividebyzero error and stops when the error occurs
MSH> $ErrorActionPreference = "Stop"
MSH> foreach ( $n in 2,1,0,1,2 ) { 1 / $n }
4.
Execute a foreach loop that causes a dividebyzero error and inquires whether execution should
continue
MSH> $ErrorActionPreference = "Inquire"
Page 12
Add a trap statement to the previous script that prints "got an error" in the case of an exception.
MSH> trap { write-object "got an error" } "hi" ; 1/$null; "bye"
hi
got an error
Attempted to divide by zero.
At line:1 char:48
+ trap { write-object "got an error" } "hi" ; 1/$ <<<< null; "bye"
bye
3.
4.
Change the trap statement to halt the script when it handles an error
5.
As you can see from the help files, it is possible to create a fairly customized view of data.
2. Create a table of process objects selecting only the name, handlecount, processid and virtual
memory size
MSH> get-process | format-table name,handlecount,processID,virtualmemorysize
3.
1.
Meaning
width
alignment
expression
label
formatstring
Create a table of process objects with two columns, processname and handlecount where the
label is "handle" and the handlecount values are centered
MSH> get-process | format-table processname,@{ label = "handle"
expression = { $_.handlecount }
alignment = "center" }
In this exercise, you will learn how to create functions and scripts and also understand how Monad
provides input and how to allow your functions and scripts to accept arguments and piped input.
Task 1 Declaring Function Names
A function is a named block of code that you can reference within your MSH commands. When you call
the function name, the code within the function runs as if you had typed in the function's code block
directly. A function can accept import values that you specify as arguments when you call the function
Page 14
or accept values that are passed to the function through the current pipeline. The function returns
values that can then be assigned to variables or passed to other functions or Cmdlets.
1.
2.
3.
Create a filter that returns the property name (as an argument called prop) of the objects it
receives
2.
Create a function that takes an array of integers as input and multiplies each object by 2
MSH> function mult2 { foreach( $number in $input ) { $number * 2 } }
MSH> 1,2,3,4 | mult2
2
4
6
8
2.
Create a function that takes an array of integers as input and multiplies each object by the
supplied argument
MSH> function multx { foreach( $number in $input ) { $number * $args[0] } }
MSH> 1,2,3,4 | multx 3
3
6
9
12
Task 4 Scripts
A script allows you to consolidate commands, functions, filters and the other constructs in a file. There
is one specific issue that scripts have with regard to accepting named parameters. If you wish a script
to accept parameters by name, you must use the param statement as the first executable line of your
script.
1. Create a script that has two parameters; "firstparam" and "secondparam", each of these
parameters should be echoed on its own line (the following is an example)
Page 15
Page 16
Lab Summary
In this lab you performed the following exercises.
Learned how Monad handles errors and how to handle errors in script
Learned how to define your own formatting of the Monad shell output
Congratulations! You now should have a good idea how expressive and powerful the Monad shell is.
We encourage you to continue to use the Monad shell in this lab. The on-line help and the lab proctors
should be able to answer any questions you might have about the shell.
Page 17
Solutions
Task 1
function sum {
$total = 0
foreach ( $number in $args )
{
trap { write-host ignoring $number; continue }
$total += $number
}
$total
}
Task 2
function rev {
foreach ( $n in $input )
{
$r = @($n) + $r
}
$r
}
Task 3
Filter match {
if ( $_ -match $args[0] )
{
$_
}
}
Page 18