Você está na página 1de 361

PowerShell for the IT

Administrator, Part 1
Student Lab Manual (v1.1)

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Conditions and Terms of Use


Microsoft Confidential - For Internal Use Only

This training package is proprietary and confidential, and is intended only for uses described in the training materials.
Content and software is provided to you under a Non-Disclosure Agreement and cannot be distributed. Copying or
disclosing all or any portion of the content and/or software included in such packages is strictly prohibited.
The contents of this package are for informational and training purposes only and are provided "as is" without
warranty of any kind, whether express or implied, including but not limited to the implied warranties of merchantability,
fitness for a particular purpose, and non-infringement.
Training package content, including URLs and other Internet Web site references, is subject to change without notice.
Because Microsoft must respond to changing market conditions, the content should not be interpreted to be a
commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after
the date of publication. Unless otherwise noted, the companies, organizations, products, domain names, e-mail
addresses, logos, people, places, and events depicted herein are fictitious, and no association with any real
company, organization, product, domain name, e-mail address, logo, person, place, or event is intended or should
be inferred.

2012 Microsoft Corporation. All rights reserved.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Copyright and Trademarks


2012 Microsoft Corporation. All rights reserved.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering
subject matter in this document. Except as expressly provided in 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.
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.
For more information, see Use of Microsoft Copyrighted Content at
http://www.microsoft.com/about/legal/permissions/
Microsoft, Internet Explorer, and Windows are either registered trademarks or trademarks of Microsoft
Corporation in the United States and/or other countries. Other Microsoft products mentioned herein may be either
registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. All other
trademarks are property of their respective owners.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 4 of 361

Contents
LESSON 1 DEMONSTRATION : INTRODUCTION ............................................................................................... 9
HOW TO USE THE EXAMPLES IN THIS WORKSHOP ............................................................................................ 10
EXERCISE 1: WINDOWS POWERSHELL ......................................................................................................... 14
EXERCISE 2: THE POWERSHELL INTEGRATED SCRIPTING ENVIRONMENT (ISE) ........................................................ 17
EXERCISE 3: POWERSHELL V2.0 INSTALLATION AND PREREQUISITES .................................................................... 20
EXERCISE 4: BASIC POWERSHELL COMMANDS ............................................................................................... 23
EXERCISE 5: RUNNING EXTERNAL COMMANDS ............................................................................................... 26
EXERCISE 6: LIST POWERSHELL COMMANDS .................................................................................................. 28
EXERCISE 7: GETTING HELP WITH POWERSHELL.............................................................................................. 30
EXERCISE 8: EXPLORE COMMAND HISTORY ................................................................................................... 32
LESSON 1 HANDS-ON : INTRODUCTION ........................................................................................................ 34
EXERCISE 1: CREATE A TRANSCRIPT OF COMMANDS ........................................................................................ 35
EXERCISE 2: USING THE MOST COMMON COMMANDS..................................................................................... 37
EXERCISE 3: RUN MULTIPLE COMMANDS ..................................................................................................... 39
LESSON 2 DEMONSTRATION : COMMANDS AND OBJECTS............................................................................ 41
EXERCISE 1: POWERSHELL COMMANDS ........................................................................................................ 42
EXERCISE 2: COMMAND ALIASES ................................................................................................................ 47
EXERCISE 3: THE OBJECT-BASED SHELL ......................................................................................................... 49
EXERCISE 4: THE .NET OBJECT MODEL ........................................................................................................ 56
LESSON 2 HANDS-ON : COMMANDS AND OBJECTS....................................................................................... 60
EXERCISE 1: POWERSHELL COMMANDS ........................................................................................................ 61
EXERCISE 2: DISCOVERING OBJECT MEMBERS ................................................................................................ 65
EXERCISE 3: CREATING OBJECT INSTANCES .................................................................................................... 68
LESSON 3 DEMONSTRATION : PIPELINE ........................................................................................................ 72
EXERCISE 1: UNDERSTAND THE FUNDAMENTAL OPERATORS .............................................................................. 73
EXERCISE 2: UNDERSTAND PIPELINE USAGE, SYNTAX, AND THE PIPELINE VARIABLE ................................................... 78
EXERCISE 3: FILTERING , SORTING, AND GROUPING DATA .................................................................................. 82
EXERCISE 4: PIPELINE INPUT AND OUTPUT .................................................................................................... 87
LESSON 3 HANDS-ON : PIPELINE ................................................................................................................... 91
EXERCISE 1: POWERSHELL OPERATORS ........................................................................................................ 92
EXERCISE 2: THE POWERSHELL PIPELINE ....................................................................................................... 94
EXERCISE 3: FILTER AND SORT WITH THE PIPELINE ........................................................................................... 98
LESSON 4 DEMONSTRATION : PROVIDERS .................................................................................................. 103
EXERCISE 1: PROVIDER I NTRODUCTION........................................................................................................104
EXERCISE 2: PROVIDER RELATED CMDLETS AND OPERATIONS............................................................................108

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 5 of 361

EXERCISE 3: SINGLE LEVEL PROVIDERS ........................................................................................................115


EXERCISE 4: MULTIPLE LEVEL PROVIDERS .....................................................................................................120
LESSON 4 HANDS-ON : PROVIDERS ............................................................................................................. 129
EXERCISE 1: WORK WITH ENVIRONMENT PROVIDER .......................................................................................130
EXERCISE 2: WORK WITH THE CERTIFICATE PROVIDER .....................................................................................133
EXERCISE 3: WORKING WITH THE REGISTRY PROVIDER ....................................................................................136
LESSON 5 DEMONSTRATION : VARIABLES AND TYPE FUNDAMENTALS ....................................................... 139
EXERCISE 1: WORKING WITH VARIABLES ......................................................................................................140
EXERCISE 2: BASIC VARIABLE TYPES IN POWERSHELL ......................................................................................145
EXERCISE 3: WORKING WITH ARRAYS .........................................................................................................153
EXERCISE 4: WORKING WITH HASH TABLES ..................................................................................................157
EXERCISE 5: WORKING WITH CONSOLE INPUT-OUTPUT ...................................................................................160
EXERCISE 6: WORKING WITH FILES .............................................................................................................162
EXERCISE 7: POWERSHELL ERROR OBJECT ....................................................................................................166
LESSON 5 HANDS-ON : VARIABLES AND TYPE FUNDAMENTALS .................................................................. 171
EXERCISE 1: WORKING WITH VARIABLES ......................................................................................................172
EXERCISE 2: WORKING WITH ARRAYS .........................................................................................................174
EXERCISE 3: WORK WITH HASH TABLES .......................................................................................................176
EXERCISE 4: WORK WITH HASH TABLES AND CALCULATED OBJECT PROPERTIES .....................................................178
LESSON 6 DEMONSTRATION : SCRIPTING ................................................................................................... 181
EXERCISE 1: SCRIPTING IN POWERSHELL ......................................................................................................183
EXERCISE 2: ITERATION STATEMENTS ..........................................................................................................189
EXERCISE 3: FLOW CONTROL STATEMENTS ...................................................................................................193
EXERCISE 4: OTHER STATEMENTS ..............................................................................................................196
EXERCISE 5: FUNCTIONS ..........................................................................................................................200
EXERCISE 6: PROFILES .............................................................................................................................206
EXERCISE 7: DOT SOURCING AND SCRIPT LIBRARIES ........................................................................................209
LESSON 6 HANDS-ON : SCRIPTING .............................................................................................................. 211
EXERCISE 1: CREATE POWERSHELL SCRIPTS ..................................................................................................212
EXERCISE 2: CREATE FUNCTIONS IN SCRIPTS .................................................................................................213
EXERCISE 3: CREATE POWERSHELL PROFILES ................................................................................................214
EXERCISE 4: EXPLORE ITERATION STATEMENTS IN POWERSHELL ........................................................................215
LESSON 7 DEMONSTRATION : ACTIVE DIRECTORY ADMINISTRATION (ADSI) .............................................. 219
EXERCISE 1: ACTIVE DIRECTORY FUNDAMENTALS ...........................................................................................220
EXERCISE 2: SEARCHING ACTIVE DIRECTORY .................................................................................................224
EXERCISE 3: THE DIRECTORY OBJECT LIFECYCLE .............................................................................................230
LESSON 7 HANDS-ON : ACTIVE DIRECTORY ADMINISTRATION (ADSI) ......................................................... 239

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 6 of 361

EXERCISE 1: CREATE MULTIPLE USERS ........................................................................................................240


LESSON 8 DEMONSTRATION : ACTIVE DIRECTORY ADMINISTRATION (CMDLETS)....................................... 244
EXERCISE 1: USING THE ACTIVE DIRECTORY MODULE .....................................................................................245
EXERCISE 2: USING THE ACTIVE DIRECTORY PROVIDER ....................................................................................247
EXERCISE 3: CMDLETS AND IDENTITY...........................................................................................................249
EXERCISE 4: SEARCHING ACTIVE DIRECTORY USING CMDLETS ............................................................................252
EXERCISE 5: CREATING ACTIVE DIRECTORY OBJECTS USING CMDLETS ..................................................................254
EXERCISE 6: MODIFYING OBJECTS USING CMDLETS ........................................................................................256
EXERCISE 7: POWERSHELL CREDENTIAL OBJECTS AND USING ALTERNATIVE CREDENTIALS FOR CMDLETS ......................257
LESSON 8 HANDS-ON : ACTIVE DIRECTORY ADMINISTRATION (CMDLETS).................................................. 258
EXERCISE 1: CREATING MULTIPLE USERS IN AN ORGANIZATIONAL UNIT ..............................................................259
EXERCISE 2: MODIFYING AD OBJECTS VIA CMDLETS .......................................................................................262
EXERCISE 3: SEARCHING AD OBJECTS VIA CMDLETS ........................................................................................264
LESSON 9 DEMONSTRATION : WINDOWS MANAGEMENT INSTRUMENTATION (WMI)............................... 267
EXERCISE 1: INTRODUCTION TO WMI .........................................................................................................268
EXERCISE 2: WMI CLASSES AND QUERIES ....................................................................................................272
EXERCISE 3: WMI REMOTING AND METHOD EXECUTION ................................................................................281
EXERCISE 4: COMMON WMI CLASSES USED ................................................................................................286
LESSON 9 HANDS-ON : WINDOWS MANAGEMENT INSTRUMENTATION (WMI).......................................... 290
EXERCISE 1: WMI CLASSES AND QUERIES ....................................................................................................291
EXERCISE 2: BASIC FILTERING ....................................................................................................................293
EXERCISE 3: WMI METHOD EXECUTION .....................................................................................................296
LESSON 10 DEMONSTRATION : REGISTRY, EVENT LOG AND ACL MANAGEMENT ........................................ 301
EXERCISE 1: USING THE REGISTRY PROVIDER ................................................................................................302
EXERCISE 2: REMOTE REGISTRY MANAGEMENT .............................................................................................310
EXERCISE 3: EVENTLOG CMDLETS...............................................................................................................315
EXERCISE 4: FILE AND FOLDER ACL MANAGEMENT ........................................................................................320
LESSON 10 HANDS-ON : REGISTRY, EVENT LOG AND ACL MANAGEMENT................................................... 322
EXERCISE 1: READING REGISTRY INFORMATION FROM A REMOTE HOST ...............................................................323
EXERCISE 2: SEARCHING EVENT LOGS FOR EVENTS .........................................................................................326
EXERCISE 3: FILE AND FOLDER ACL MANAGEMENT ........................................................................................330
LESSON 11 DEMONSTRATION : REMOTING................................................................................................. 334
EXERCISE 1: REMOTE MANAGEMENT WITHOUT POWERSHELL REMOTING ............................................................335
EXERCISE 2: ENABLE POWERSHELL REMOTING ..............................................................................................338
EXERCISE 3: ENABLE POWERSHELL REMOTING WITH THE ACTIVE DIRECTORY GROUP POLICY OBJECT (GPO)................340
EXERCISE 4: EXECUTE A SINGLE REMOTE COMMAND OR SCRIPT ........................................................................342
EXERCISE 5: CREATE A PERSISTENT SESSION TO EXECUTE A SERIES OF REMOTE COMMANDS .....................................345

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 7 of 361

EXERCISE 6: CREATE AN INTERACTIVE SESSION WITH A REMOTE MACHINE ...........................................................348


EXERCISE 7: CREATE A SESSION CONFIGURATION ...........................................................................................350
LESSON 11 HANDS-ON : REMOTING............................................................................................................ 354
EXERCISE 1: EXECUTE REMOTE COMMANDS .................................................................................................355
EXERCISE 2: EXECUTE COMMANDS VIA SESSIONS ...........................................................................................357
EXERCISE 3: INTERACTIVE REMOTE CONSOLE ................................................................................................359

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 8 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 1: PowerShell Introduction

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 9 of 361

Lesson 1 Demonstration : Introduction


Introduction
The way this lesson is presented is a little different to what you might be used to. You would
have noticed that there is no workbook and that we are starting with the lab manual. What we
are going to do is walk through some examples as an instructor led lab format and then you
will complete some lab exercises by yourself.

Objectives
After completing this lab, you will be able to:

Understand the basic use and capabilities of Windows PowerShell

Meet the pre-requisites and install Windows PowerShell

Run basic PowerShell commands

Use PowerShell help to get help about PowerShell commands

Prerequisites
To complete this lab, you need:

A Windows 7 workstation logged onto with administrator credentials. You can logon as
contoso\administrator. The password is P@ssword

Estimated Time to Complete this Lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 10 of 361

How to use the Examples in this Workshop


The way with lesson will be presented will be a little different to what you may be used to.
You would have noticed that there is no workbook and that we are starting with the lab
manual. What we are going to do is walk through the examples together as an instructor led
lab format, and then you will do some more lab exercises by yourself. There are three options
you can choose from for following the examples:

Manually type in the commands

Open the command files in the PowerShell Integrated Scripting Environment (ISE) and
execute each command by selecting each one

Using the automated start-demo PowerShell script to run each command automatically

Each option is a matter of preference. The first option will familiarize you with the
commands. This is the slowest option and you may have problems keeping up with the
instructor, but this is a great option to run through after the workshop at your own pace to
consolidate your learning.
The second and third options are easier as they do not require type each command. However,
as you are not typing each command you may miss some commands.
If you use the second option, the command file can be opened and commands can still be
typed using the command pane. This allows you to run some of the command from the file
and type others.
The third option is the easiest option to run the demo commands. However, you cannot enter
additional commands manually. This can be easily solved by opening a second PowerShell
console and typing the additional commands.

Option 1: Run Commands Manually


This option is to type the command in manually as they appear in the code blocks of each
example. You can use tab completion in PowerShell to reduce typing time. Also You can use
the up arrow to select the most recent commands executed if you need to build from the
previous command.

Option 2: Use of Command Files and the ISE


To use the ISE and the command files, change the default view of the ISE to maximize the
Real Estate screen. To maximize the Real Estate screen,
1. Select the Start button to open the PowerShell ISE.
2. Type ISE and run the Windows PowerShell ISE.
By default, it will appear as follows:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 11 of 361

Figure 1

3. Click one of the three rightmost buttons in the toolbar to adjust the pane arrangement.
This makes it easier to follow all examples.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 12 of 361

Figure 2

In this view,
1. Open the command file, or files for the lesson.
2. Select each line that does not start with #.
3. Press F8 or right-click and select Run or click the

icon on the toolbar.

Option 3: Use of Start-Demo Script


Using the start-demo script is the easiest option. To use this option, your PowerShell console
should be opened as normal and the location should be changed to C:\Pshell\part1\lesson1
for lesson 1.
1. To change the location, type:
set-location c:\pshell\part1\lesson1

2. Now type the following command to load the start-demo.ps1 script function into the
memory:
. .\start-demo.ps1

The dot and space before .\start-demo are required.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 13 of 361

3. Now type the following command to start the demo script:


Start-demo <demo_script.txt>

Where <demo_script.txt> is the demo script file for the lesson or exercise.
Note: To exit the demo script at any time you can use the ctrl + c keys.

The script will display the last line number used.


4. To restart the script type the following command:
Start-demo <demo_script.txt> <line number>

Where line number is the number of the line to re-start from.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 14 of 361

Exercise 1: Windows PowerShell


Objectives
In this exercise, you will:

Learn what Windows PowerShell is

Open Windows PowerShell and run some basic commands

Scenario
Welcome to Windows PowerShell.
Windows PowerShell is both a command shell and a scripting language. A significant
difference between PowerShell and other shells is that it is an object-oriented shell. This
aspect of PowerShell will be discussed in detail later.
The use of Windows PowerShell can be divided into two main areas:

Running commands from the command shell interactively

Running scripts

Running scripts will be discussed later. For now, we will discuss running commands in the
shell. Both categories of use of PowerShell are powerful. Depending on the task being
performed will determine which category to use. For example, Exchange 2007 or 2010
administrators will be familiar with running commands in the command shell but they may
not be familiar with running scripts. We will start with opening PowerShell and running
commands in the console.

Task 1: Log on to the VM Environment


1. Log on to the Windows 7 client.
2. Open Windows PowerShell and run the required commands.

Task 2: Open Windows PowerShell for the First Time


There are different methods to open Windows PowerShell. Each method has its own purpose.
The first one we use is the simplest.
1. Open PowerShell.
2. On the Windows taskbar, click

(PowerShell icon).

The PowerShell window appears.


You will notice that it looks different to the standard command prompt. It should have a
blue background and white text. It will also have the text
PS C:\users\administrator> PS indicates that you are using PowerShell and not the
CMD shell.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 15 of 361

Task 3: Run the First Command


1. Type the following command:
dir

You will see that now you have displayed the files and folders that are available from
your current location. Let us compare the PowerShell display and the CMD shell display.
2. Click Start > Run, type cmd and press Enter.
3. In the CMD shell, type the following command:
dir

4. Compare the output of PowerShell and the output of the CMD shell.
You will notice that they are very different. The main advantage of PowerShell is that it
is easy to change the view.

Task 4: Change PowerShell View


1. In the PowerShell console, type the following command to display the file system
objects:
dir | format-table name, lastwritetime, length

You will see that we now have the same information but it appears very differently. Now
let us open PowerShell from the run box. It will look different.
2. Click Start > Run, type powershell and press Enter.
The PowerShell prompt appears, but this time you will see it looking more like the CMD
shell, as it has the black backgorund and the grey text. Note that it will have the PS
C:\users\administator> prompt.
3. In the PowerShell console, type the following command to display the file system
objects:
dir | format-table name, lastwritetime, length

You will notice that the output is the same as in the blue background window. Now, close
the black background window and let us run another command in the blue background
window.
4. Type the following command to display processes.
get-process

A list of all the processes running on your machine appears. Now, run the same command
from the command prompt.
5.

Click Start > Run and type the following command:


powershell command get-process

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 16 of 361

You will see the command run and produce the output, but the window closes as soon as
it finishes running the command. To prevent this, you have the option of keeping the
window open after you run the command. You will do this now using the noexit option.
Note that this needs to be before the command option.
6. Click Start > Run and type the following command:
PowerShell noexit command get-process

You will now see that the command is executed and the window stays open. You can
explore other options for running PowerShell.exe and commands by typing PowerShell /?

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 17 of 361

Exercise 2: The PowerShell Integrated Scripting


Environment (ISE)
PowerShell v2.0 comes with its own graphical scripting editor known as the ISE. The ISE is a
fully integrated scripting environment that both aids in using PowerShell and enhances it. The
ISE is installed by default on Windows 7 machines, and installed automatically on
workstations as part of the Windows management framework package (that includes
PowerShell v2). On Windows Server 2008 R2, it is a feature that you have to enable, or select
to install on other operating systems. Once you have the ISE available then it can be run.
1. On your workstation click Start > Run and type PowerShell ISE and press Enter.
The PowerShell ISE opens and you will see the three parts of it.

Figure 3

Script Pane
Allows you to create and run scripts. You can open, edit, and run existing scripts in the
Script Pane.

Output Pane
Displays the results of the commands and scripts you have run. You can also copy and
clear the contents in the Output Pane.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 18 of 361

Command Pane
Allows you to type commands. You can run a one-line command or a multi-line
command in the Command Pane. Press SHIFT+ENTER to enter each line of a multiline
command, and press Enter after the last line to execute the mult-line command. The
prompt displayed on top of the Command Pane shows the path to the current working
directory.
From here, we can run PowerShell commands and view the results.

Task 1: Run PowerShell


1. Click the Command pane and type the following command:
dir | format-table name, lastwritetime, length

You will now see in the output pane the results of the command. This is just like having a
PowerShell console open, but we are running these commands from within the ISE. Now
will we run some commands from the script pane.
2.

Click the Script pane and type the following:


get-process

You can open the file _ISE-commands.ps1 if you do not want to type the commands.
3. On the next line, type the following command:
dir | format-table name, lastwritetime, length

4. On the next line type the following:


write-host Hello from PowerShell!

You will notice that the ISE will now color code the different parts of each command.
This is to help identify the different parts of each command such as the command part,
and strings code blocks.

Task 2: Run All Commands


You can now run all commands using the Run button(or press F5) or select the line or part of
the line to be run.
1. Drag and select the text you want to run.
2. Use the Run selection button or press F8 to run the command.
3. Select the first line that has get-process and select the text.
4. Select the Run selection button or press F8 to run the command.
You will see that in the output pane, you have the results of the get-process command.
5. Select the second line with dir | format-table name, lastwritetime, length and run this
selection.
The output for this command appears in the output pane.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 19 of 361

6. Click the Run button or press F5 to run all the commands.


You will see the output of all commands.
7. Keep the ISE open and run commands in it, or close the ISE and run commands in the
PowerShell.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 20 of 361

Exercise 3: PowerShell V2.0 Installation and


prerequisites
Before you run PowerShell, you must make sure it is available. PowerShell v2.0 is installed
by default on Windows 7 and Windows Server 2008 R2. Therefore, for these operating
systems you do not have to do anything additional to make PowerShell available.
For operating systems other than Windows 7 and Windows Server 2008 R2 , you will need to
download and install the Windows Management Framework package. It is available from
http://support.microsoft.com/default.aspx/kb/968929. This package will install Windows
PowerShell 2.0, WinRM 2.0, and BITS 4.0. The update can be installed on the following
operating systems:

Windows Server 2008 with Service Pack 1

Windows Server 2008 with Service Pack 2

Windows Server 2003 with Service Pack 2

Windows Vista with Service Pack 2

Windows Vista with Service Pack 1

Windows XP with Service Pack 3

Windows Embedded POSReady 2009

Windows Embedded for Point of Service 1.1

In addition to the Windows Management Framework package, the .NET framework 3.5 SP1
is also required on the system to install PowerShell v2.0.
Although PowerShell v1 is available, there are many new features of PowerShell v2.0 that
should be considered. PowerShell v1 is available for the following systems:

Windows Server 2003 with Service Pack 2

Windows XP with Service Pack 3

PowerShell v1.0 is installed by default, on Windows Vista and as a feature for Windows
Server 2008. The requirements for PowerShell v1.0, are that the .NET framework 2.0 is
installed on the system. At this stage, it is not recommended that PowerShell v1 be installed,
as v2 has many additional features available.
By default, all versions of PowerShell will have the execution of scripts disabled. This has to
be turned on either by the command set-execution policy or via group policy/registry settings.
For PowerShell v2, PowerShell Remoting is also disabled by default. This has to be enabled
with the command enable-psremoting or via group policy/registry settings.

Task 1: Determine the PowerShell Version


There are several ways you can determine the version of PowerShell you are currently
running, or is available on a machine. We will look at several of these and a few things of
note.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 21 of 361

Use of $host.version
1. In the PowerShell console, type the following command to display the version:
$host.version

This will now display the version number of Windows PowerShell. The number to take
the most note of is the major version number.

Use of $psversiontable
1. In the PowerShell console, type the following command to view the ps version table:
$psversiontable

This table of version numbers not only gives you the version of PowerShell installed but
also lists the version of other related components. This is useful when you start looking at
some of the advanced features of PowerShell such as remoting. The number to take
interested in here is the PSVersion number.

Use of Registry
You can also check the version of PowerShell installed on a machine by checking the registry.
This can be very useful, as it will allow us to check the version of PowerShell installed on a
remote machine without having to run commands in a PowerShell console.
1. In the PowerShell console, type the following command to get the version information
from the registry:
get-itemproperty HKLM:\software\microsoft\PowerShell\1\PowerShellEngine

You will now see the information from the registry key. The properties to take note of are
the runtimeversion and the powershellversion number.
You can use the same path on a remote machine to check the PowerShell version
installed on the target. This will be discussed later.

Use of PSSnapins
By looking at the versions of the PowerShell snapins you can determine the version of
PowerShell and see the versions of each snapin that makes up the collections of PowerShell
Cmdlets.
1. In the PowerShell console, type the following command to list the PowerShell snap-ins:
get-pssnapin

You will now see the current PowerShell snapins and their PowerShell version numbers.

Points to Note About PowerShell v2.0


There are a few things to take note of when looking at PowerShell and its version. Several
things such are registry paths, file extensions and install locations did not change between
PowerShell v1 and PowerShell v2. These can cause confusion about the version of
PowerShell that is in use. First to note is that the file extension .PS1 is still the script file
extension for PowerShell v2.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 22 of 361

The next is the PowerShell install location.


1. In the PowerShell console, type the following to set the location to the PowerShell install
location:
$pshome

This variable contains the path to the PowerShell install location. Note that even on a
machine with PowerShell v2 installed, this still points
to %systemroot%\ System32\WindowsPowerShell\v1.0.
The registry path for PowerShell v2 is also HKLM:\software\microsoft\PowerShell\1\.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 23 of 361

Exercise 4: Basic PowerShell Commands


In this exercise, you will run some basic PowerShell commands. PowerShell allows you to
run both PowerShell commands, many of these called Cmdlets, and external commands such
as executable. First, you need to create a transcript to record all the commands you type. This
will log all commands and the output they produce.
1. In the PowerShell console, type following command to start a transcript
start-transcript PowerShell_transcript.txt

This will now start the transcript recording our commands.


You will get a quick list of the commands available to run in PowerShell. To do this, use
the Cmdlet called get-command.
Transcript commands will not work if you are running the demos from within the ISE

2. In the PowerShell console, type the following command to list the commands available.
get-command

A list of commands available to you under the current PowerShell console appears.
However, you will notice that this list contains different types of commands. For now,
you need only Cmdlets. Use get-command to display only the Cmdlets.
3. In the PowerShell console, type the following command to list Cmdlets:
get-command commandtype cmdlet

This will now list just the Cmdlets. You will notice it is a much shorter list than before. In
fact you can use PowerShell to tell exactly how many Cmdlets there are. You can do this
easily using two different methods.
4. In the PowerShell console, type the following command to count the Cmdlets available:
get-command commandtype cmdlet | measure-object

The count of available Cmdlets appears. By default, in Windows 7 the count should be
236 at the time of writing. There is another way to do this.
5. In the PowerShell console, type the following command to count the Cmdlets available:
(get-command commandtype cmdlet).count

The number of Cmdlets appears. However, this time you will see only the number.
Now let us run some more commands.
1. In the PowerShell console, type the following command to get the current date:
get-date

The current date and time appears. You can change what appears by using some
parameters in the command.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 24 of 361

2. In the PowerShell console, type the following command to get just the date:
get-date displayhint date

Only the date appears.


3. In the PowerShell console, type the following command to get only the current time:
get-date displayhint time

Only the time appears.


You can also view different time formats.
1. In the PowerShell console, type the following to display the short date format:
get-date displayhint time format d

2. In the PowerShell console, type the following command to display the long date format:
get-date displayhint time format D

3. In the PowerShell console, type the following to display the short time format:
get-date displayhint time format t

4. In the PowerShell console, type the following command to display the long time format:
get-date displayhint time format T

5. In the PowerShell console, type the following to display the date in a given format:
get-date displayhint time format yyyy/MM/dd

This will display the date in the given format. Note that this is case sensitive. Note also
that you should always use ISO8601 for dates rather than a specific locale.
6. In the PowerShell console, type the following command to display time in a given
format:
get-date displayhint time format hh:mm:ss

This will display the time in the given format. Again, note that this is case sensitive and
the lower-case mm produces minutes, whereas the upper-case MM produces the
month.
Let us look at something more interesting.
1. In the PowerShell console, type the following command to list the current processes:
get-process

A list of the currently running processes appears. We can do the same with services.
2. In the PowerShell console, type the following command to list the services on the system:
get-service

A list of services and their statuses appears. However, you might be interested in only
one service. You can view this by typing its name after get-service.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 25 of 361

3. In the PowerShell console, type the following command to get information for just the
bits service:
get-service bits

Now you will see information about only the bits service
4. In the PowerShell console, type the following command to generate a random number
between 1 and 10:
Get-random Minimum 1 Maximum 10

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 26 of 361

Exercise 5: Running External Commands


The great thing about PowerShell is that you do not have to call the external command with
anything special to get them to run. You can run the command by typing the name of the
command and pressing Enter.
1. In the PowerShell console, type the following command to get IP configuration
information:
ipconfig

You will now see that you have the same output that you would have had if you run the
command in the CMD shell.
2. In the PowerShell console, type the following command to get all IP configuration
information:
ipconfig /all

You will again see the same output as the CMDshell.


3. In the PowerShell console, type the following command to get system information:
systeminfo

This will now list a summary of the system information of the current machine.
What may be useful is to write this information to a file. Just like the CMD shell, you can
use the > and >> symbols to redirect the output. > will overwrite the output, whereas >>
will append the output.
4. In the PowerShell console, type the following command to redirect output to a file:
systeminfo >systeminfo.txt

This will now write that information to a text file for us. To view it lets use notepad
5. In the PowerShell console, type the following command to open the text file in notepad:
notepad systeminfo.txt

You will now see the information from the command in the text file. This not only works
for external commands, but also for Cmdlets.
6. In the PowerShell console, type the following command to redirect the Cmdlet output to
a file:
get-service > services.txt

7. In the PowerShell console, type the following command to read the file:
notepad services.txt

The information about services appears.


You can also get PowerShell to run multiple commands in a sequence. This can be useful as
you can put multiple commands in one line and PowerShell will run these in a sequence. This

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 27 of 361

is especially useful if you have a command that takes a while to run and you do not want to
wait until it is finished. To do this, use the semicolon character. This is the statement
terminator for PowerShell.
1. In the PowerShell console, type the following command to run multiple commands, add
multiple items to a text file and open it in Notepad:
ipconfig /all > systemconfig.txt; systeminfo >>systemconfig.txt ; get-service
>>systemconfig.txt; notepad systemconfig.txt

The three commands to get information about the system will now run, and each of these
will put information into the systemconfig.txt. Finally, open Notepad to view this
information.
The $lastexitcode variable can be very useful when working with external commands. This
variable contains the exit code or errorlevel value from the external command. In general, an
exit code of zero is a success and anything non-zero is considered an error of some type.
However, this may not be true depending on the program you are running. Let us look at a
simple example using the ping command.
1. In the PowerShell console, type the following command to ping the local machine:
ping localhost

2. In the PowerShell console, type the following command to check the status of the
previous command:
$lastexitcode

You will now see that the value of the $lastexitcode is now zero. This is because we were
able to ping the localhost.
3. In the PowerShell console, type the following command to ping a non-existing host:
ping fakeserver

4. In the PowerShell console, type the following command to check the status of the
previous command:
$lastexitcode

You will now see that the value of the $lastexitcode is now one. This is because, you
were unable to ping the fakeserver host, as it does not exist.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 28 of 361

Exercise 6: List PowerShell Commands


You looked at listing available PowerShell commands quickly a little while ago. But it is
worth spending a little more time on this as it is difficult to remember around 236 or more
commands. There will be a number of Cmdlets that you will use repeatedly, and some you
may never use. To help you find Cmdlets in PowerShell we have the get-command Cmdlet.
This can be used in a number of ways to find the commands that you are interested in.
1. In the PowerShell console, type the following command to list the commands available:
get-command

You will now see a list of Cmdlets, functions and alias. This does work a little differently
in PowerShell v1 and v2. In v1 you would have only seen Cmdlets by default.
2. In the PowerShell console, type the following command to list just Cmdlets:
get-command commandtype cmdlet

You will now see a list of just the Cmdlets available.


Now, let us look for commands that start with get.
3. In the PowerShell console, type the following command to list all the command that start
with get:
get-command

get*

A list of commands that start with get appears. You will notice that most of these are
Cmdlets. However, there are some external commands such as getmac.exe and
gettingstarted.exe listed. This is because, these are commands that PowerShell can run.
You will notice that these external commands are listed as the type of application. This
tells you that it is an external command. If you combine the last two options, commandtype and get* you will see only the Cmdlets.
4. In the PowerShell console, type the following command to list just Cmdlets that start
with get:
get-command commandtype cmdlet get*

Now, you will see just Cmdlets that start with get. There is an easier way to do this.
You can use the -verb option to look for Cmdlets or functions.
5. In the PowerShell console, type the following command to list Cmdlets with the verb get:
get-command verb get

You will now see any Cmdlets and functions that have the verb get in their name. We
will go into more details about the naming of Cmdlets later, but you will find that the
names of the Cmdlets follow verb-noun in their names. This makes it easy to know what
a Cmdlet might do, but also makes is easy to find the Cmdlets.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 29 of 361

6. In the PowerShell console, type the following command to list Cmdlets with the noun
service:
get-command noun service

7. You will now see all the Cmdlets that are related to services. We can also do this with a
wildcard search.
8. In the PowerShell console, type the following command to get all commands that end
with service:
get-command *service

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 30 of 361

Exercise 7: Getting Help with PowerShell


One of the useful things with PowerShell is that it has a great built-in help system. All
Cmdlets have a help topic and these topics have both, a consistent format and a consistent
method for accessing it. This is all done with the Cmdlet get-help. In addition, to having
help information for Cmdlets, there are also additional help topics covering PowerShell
concepts,
1. In the PowerShell console, type the following command to display the help details:
get-help

The help information for the get-help Cmdlet appears. You will notice that information
follows a particular format. The good thing is that this format is the same for all Cmdlets.
2. In the PowerShell console, type the following command to get help on the get-command
Cmdlet:
get-help get-command

The help information for the get-command Cmdlet appears. You can expand on this by
using two options.
3. In the PowerShell console, type the following command to get a detailed help on getcommand:
get-help get-command detailed

Some of the same information as before appears on top of the display. However, as you
scroll down you will find more information such as the parameter descriptions and some
examples. Let us do this again with a different Cmdlet.
4. In the PowerShell console, type the following to get detailed help on get-service Cmdlet:
get-help get-service detailed

The detailed help information for the get-service Cmdlet appears. There is another option
that is useful, the full option. This will display all the help information for the Cmdlet.
5. In the PowerShell console, type the following to get all help on get-service Cmdlet:
get-help get-service full

The full help information for that Cmdlet appears.


Another option that can be a great way to jog your memory about how a Cmdlet works is the
examples option. This will display some examples of how to use the Cmdlet.
6. In the PowerShell console, type the following command to get just examples of the getservice Cmdlet:
get-help get-service examples

In addition to getting help on Cmdlets, there are many other help topics available. To see
them we will use the following command.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 31 of 361

7. In the PowerShell console, type the following command to list all help topics:
get-help *

The full list of help topics available appears. You will see the alias, the functions,
Cmdlets and finally the helpfile topics. You will notice that all the helpfile topics all have
the name about_ this allows us to look just at them.
8. In the PowerShell console, type the following command to list just the about topics:
get-help about

Only the information about helpfile topics appears.


9. In the PowerShell console, type the following command to display the wildcards help
topic:
get-help about_wildcards

The information about PowerShell wildcards appears. Note that there is no full or
detailed option with the about topics.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 32 of 361

Exercise 8: Explore Command History


One of the things that can help a lot in the early stages of learning PowerShell is to look at the
history of the commands that you have run. This can be done in a few different methods, but
we will look at the two main methods.
The first is using the get-history Cmdlet to display the previous commands run.
1. In the PowerShell console, type the following command to view the command history:
get-history

The previous commands run up to a default maximum of 64 commands. You will notice
that each command has an ID associated with it. This ID can be used to re-run a
particular command.
2. In the list of commands, locate the ID for the get-help and get-service commands.
3. In the PowerShell console, type the following command to invoke the command from
history:
invoke-history id <that ID from above>

The command executes again. This can be useful when you have complicated lines of
code and you do not want to use the up arrow to go through all commands again.
The previous commands can also be exported and later imported to use again.
1. In the PowerShell console, type the following command to export the history to a csv file:
get-history | export-csv myhistory.csv

The command history is exported to a CSV file.


2. Open a new PowerShell console and type the following command to view the current
history:
get-history

As this is a new PowerShell session, you will see that there currently are no commands in
the history. You can now import the commands from the CSV file we created to include
some history commands that can be invoked.
3. In the new PowerShell console, type the following command to import the history from
the other session:
import-csv myhistory.csv | add-history

4. In the new PowerShell console, type the following command to view the current history:
get-history

You will now see that there are commands loaded into the history and can be invoked.
Notice that the IDs will not be the same as the session that we exported the information
from.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 33 of 361

One thing to note is that by default, you will only see the last 64 commands. This number
is defined by the variable $MaximumHistoryCount.
To increase the maximum commands:
1. In the original PowerShell console, type the following command to increase the
maximum command history count:
$MaximumHistoryCount = 100

This will allow you to look at up to 100 previous commands. You can also specify
count 100 for get history to display the 100 commands. By default, you will only get 32
displayed.
2. In the PowerShell console, type the following command to get the last 100 commands:
get-history count 100

There is another way of viewing the previous commands run. However, this will also
show the output produced from each of these.
If you remember, earlier in the lesson, we created a transcript. This will have recorded all the
previous commands that we have run. So let us stop and view the contents of that transcript.
1. In the PowerShell console, type the following command to stop the transcript:
Stop-Transcript

This will stop recording of the session and tell you where the output file is.
Again, remember here (and moving forward through the additional demonstrations) that
transcript commands will fail if being run through the ISE.

2. In the PowerShell console, type the following to read the transcript:


notepad <your transcript file>

By reading the file, you will see the history of all the commands you have run. This file
should be kept for later use, as it can be useful to look at the commands you have run.
It is suggested that at least for the next few lessons, start a transcript for each lesson so that
you can review those later.
In addition to the history Cmdlets, you can also use the up arrow to see the previous
commands run. To run the same command again, press Enter. You can also use the up arrow
to bring up a previous command and modify it. The drawback here is that if you need to go
back several commands, or you need to re-run multiple commands, the order of these
commands will change each time a new command is executed.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 34 of 361

Lesson 1 Hands-On : Introduction


Objectives
The objectives for this lab are:

To create transcripts of PowerShell commands

To practice using the top 3 Cmdlets (i.e. get-help, get-command and get-member)

To execute multiple commands in a single line

Prerequisites

The lab requires a Windows 7 client running in a domain environment.

Estimated time to complete this lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 35 of 361

Exercise 1: Create a Transcript of Commands


Objectives
In this exercise, you will:

Practice creating transcripts of PowerShell commands

Task 1: Log on to the VM environment


1. Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window appears.

Task 3: Record commands in a text file


1. Type the following in the PowerShell console. This will NOT work in the PowerShell
ISE as transcripts are not supported under the ISE Host.
new-item -path $home\documents -name transcripts -type directory

This will create a new directory for storing transcript files.


2. Type the following to set the transcript variable to a desired location for storing transcript
files
$global:transcript=$home\documents\transcripts\$((getdate).tostring("yyyyMMddHHmmss")).txt

Note: This global variable will be lost when the PowerShell session is terminated. The
variable assignment can be added to a Profile if it is required to persist between
sessions.
Note also that you should always use ISO8601 for dates rather than a specific locale
as shown in tostring("yyyyMMddHHmmss")) above.

3. Type the following to start the recording part of this PowerShell session in a text file.
start-transcript.

4. Enter some commands, for example:


Get-command
Get-service
Get-process
Get-help

5. Type the following to stop recording this PowerShell session.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 36 of 361

stop-transcript

Note that the file path and name appears on the console.
6. Type the following to view the transcript file name.
notepad $transcript

7. Type the following to start recording again.


start-transcript

8. Enter some commands, for example:


Get-command -commandtype Cmdlet

9. Type the following to stop recording this PowerShell session.


stop-transcript

Note that the file path and name appears on the console.
10. Type the following to view the transcript file name.
notepad $transcript

Note that the same file is used and the previous content was overwritten.
11. Type the following to start recording again
start-transcript -append

12. Enter some commands, for example:


Get-command -commandtype alias

13. Type the following to stop recording this PowerShell session.


stop-transcript

Note that the file path and name appears on the console.
14. Type the following to view the transcript file name.
notepad $transcript

Note that the same file is used and the previous content is still available.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 37 of 361

Exercise 2: Using the Most Common Commands


Objectives
In this exercise, you will:

Practice using the most common and useful PowerShell commands

Task 1: Log on to the VM environment


1. Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window opens.

Task 3: Get-Help, Get-Command and Get-Member


1. Type the following to view the full help available on using the get-help Cmdlet.
2.

get-help get-help -full

Type the following to view help for the get-command Cmdlet.

get-help get-command

3. Type the following to view help for the get-member Cmdlet.


get-help get-member

4. Type the following to return the methods and properties that are available for the output
of the (get-help get-command) command.
(get-help get-command) | get-member

5. Type the following to return only the properties that are available for the output of the
(get-help get-command) command.
(get-help get-command) | get-member -membertype noteproperty

6. Type the following to return only the methods that are available for the output of the (gethelp get-command) command.
(get-help get-command) | get-member -membertype method

7. Type the following to display the command syntax only.


(get-help get-command).syntax

8. Type the following to display all the parameters of the command.


(get-help get-command).parameters

9. Type the following to view the static members of the datetime type.
[datetime] | get-member -static

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 38 of 361

A. Type the following to view the current date and time.


[datetime]::now

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 39 of 361

Exercise 3: Run Multiple Commands


Objectives
In this exercise, you will:

Explore running multiple PowerShell commands in a single line

Task 1: Log on to the VM environment


1. Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window opens.

Task 3: Multiple Commands


1. Type the following series of commands on a single line write-output. The text is
wrapped here due to the page width.
Write-Output Asset Information`n |
out-file $home\documents\assetinfo.txt; get-date |
out-file $home\documents\assetinfo.txt -append; $Env:COMPUTERNAME |
out-file $home\documents\assetinfo.txt -append; get-service |
out-file $home\documents\assetinfo.txt append

2. Type the following command to view the asset information.


notepad "$home\documents\assetinfo.txt"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 40 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 2: PowerShell Commands
Student Lab Manual

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 41 of 361

Lesson 2 Demonstration : Commands and objects


Introduction
This lab introduces PowerShell commands, known as cmdlets. You will learn about cmdlet
usage, discovery and syntax for a complete understanding of their importance. You will also
understand the concept of objects, which is fundamental to using PowerShell effectively.

Objectives
After completing this lab, you will be able to:

Explore command discovery, syntax and usage

Leverage command help topics

Discover & create command aliases

Explain the usage of classes, objects & various object models in PowerShell

Pre-requisites
To complete this lab, you need:

A Windows 7 workstation logged onto with administrator credentials

Estimated time to complete this lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 42 of 361

Exercise 1: PowerShell Commands


Objectives
In this exercise, you will:

Learn command syntax

Learn command usage

Find command help

Discover commands and their grouping

Scenario
PowerShell consists of four types of commands:

Cmdlets

Functions

Scripts

External commands

In this exercise, we will focus on using the first type of commands, known as Cmdlets
(pronounced command-lets).
Cmdlets are commands built-in to PowerShell. They are written in a .NET language (C#,
VB.NET, F#, etc.) and compiled into a dynamic link library (.DLL) file.
236 Cmdlets are available by default in PowerShell v2.0 and cover a wide range of uses, from
interacting with the file system to listing event log and service information.
Although out-of-scope for this lesson, it is worth noting that new Cmdlets authored and
compiled by a developer can be loaded into the PowerShell process, alongside the default
Cmdlets.

Task 1: Understand the Command Syntax


Commands have a verb-noun naming convention, where the verb describes the action to take
on the noun. Nouns are always named in a singular way (Process rather than Processes). It is
also worth noting that PowerShell is not case sensitive.
Command names are followed by a number of hyphen-prefixed parameter names which may
be paired with an argument and are known as named parameters. All parameters and their
arguments are separated by one or more space characters. Parameter arguments can also be
inferred by their position in the command without specifying the parameter name. These are
known as positional arguments.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 43 of 361

Name

Verb-Noun

Switch Parameter

Parameter with argument

parameter1

parameter2 <argument2>

Positional argument

<argument3>

1. Open the PowerShell console or ISE and type the following command:
Get-Process

This command will return a list of all processes running on the local machine.
2. To limit the number of processes returned, add a parameter and an argument. The
following example uses the Get-Process Cmdlets Name parameter.
Get-Process -Name explorer

This will return a single line of information about the explorer process running on the
local machine.
3. Parameter names can also be shortened by abbreviating them to a unique value.
Get-Process -Na explorer

4. Next, try typing the same command using PowerShells tab-completion feature. Type the
following:
Get-

Then, press the Tab key until the full command name appears. Pressing SHIFT+TAB
moves backwards through the list.
5. This feature also works with parameter names. Type a space character and a hyphen
character. Pressing the Tab key will cycle through all the parameters for a particular
command. Again, pressing Shift+Tab moves backwards through the list.
Get-Process -<press tab key>

6. Certain parameter names can be omitted entirely with the command still working as
expected. Below, the argument explorer is associated with the Name parameter by its
position in the command. Remember that the arguments have to be passed in the default
order specified by the Cmdlet.
Get-Process explorer

7. Many parameters also accept a list of arguments, allowing more than one value to be
bound to a parameter. In PowerShell, lists can be specified by separating each item with a
comma.
Get-Process Name explorer,system,wmiprvse

8. Now add a parameter that does not require an argument. Such parameters are called
switch parameters, since they change the command's behavior by enabling a feature
within it.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 44 of 361

For example, the module switch parameter of the Get-Process Cmdlet turns on a feature
that lists all the .dll files loaded by the returned process.
Get-Process -Name explorer -Module

9. If you omit any required parameters, PowerShell will prompt you to supply the required
arguments automatically. In the example below, you are prompted for the -Path and Type parameter arguments to successfully create a new folder on the local C: volume.
PS C:\Users\Administrator> New-Item
cmdlet New-Item at command pipeline position 1
Supply values for the following parameters:
Path[0]: c:\test
Path[1]:
Type: directory
Directory: C:\
Mode
---d----

LastWriteTime
------------11/08/2011 10:00 PM

Length Name
------ ---test

Task 2: Search for Commands (Get-Command)


In this task, you will understand how to search for Cmdlets. To do this, use a Cmdlet
designed specifically for this purpose. The Get-Command Cmdlet returns a list of commands.
1. Open the PowerShell console or ISE.
2. Type the following command and press Enter:
Get-Command

A list of Cmdlets, Functions and Aliases will be displayed, since all command types are
listed by default.
3. If you were searching for a command containing a particular string you can enclose it in
wildcard (*) characters.
Get-Command *item*

4. Get-Command also has verb and noun parameters which allow you to limit the search
to commands matching the verb and/or noun part of the name. Below we list all the
Cmdlets where the word on the left-hand side of the hyphen, the verb, matches the string
get.
Get-Command verb get

Wildcard characters can also be used in parameter arguments.


5. List all the commands where the noun part of the name starts with the string object.
Get-Command noun object

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 45 of 361

6. List all commands where the verb part of the name ends with the letter w.
Get-Command verb *w

Task 3: Get Command Help (Get-Help)


PowerShell has an extensive help system accessible through the Get-Help Cmdlet. The
Cmdlet can return the syntax, description, parameters and examples for any command.
1. To use this Cmdlet, type the name of the command you want help for as the first
argument.
Get-Help New-Item

This use of the command displays basic help information. Get-Help also has a number of
switch parameters that control the amount of help information returned. The -full
parameter returns all information about a particular command.
Get-Help Get-Service -full

The -examples parameter lists different ways in which a command can be used.
Get-Help New-Item -examples

The -detailed parameter adds examples and descriptions to the basic help.
Get-Help New-Item -detailed

As with all commands, wildcard characters can be used to return help for multiple
matches. If only one command matches, PowerShell returns the help for that command. If
not, a list of matching help topics is displayed.
Get-Help new*

Another useful switch parameter for this Cmdlet is -Online. If you have internet access,
this parameter will open the TechNet Windows PowerShell command Help Topics
documentation for the specified command. http://technet.microsoft.com/enus/library/dd347701.aspx.
Get-Help New-Item -Online

2. Get-Help can also be used to display conceptual help about the PowerShell Language.
This is accessed by using the argument about_*, which will list all of the conceptual help
topics.
Get-Help about_*

You can then choose the topic and use its full name to list the entire help file.
Get-Help about_Command_Syntax

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 46 of 361

Note: A very useful piece of information returned by all the Get-Help switch parameters
is the command syntax. This has a special format that is easy to understand, once you
know how to interpret it!
<cmdlet name>

Microsoft | Services

-<Required
[-<Optional
[-<Optional
[-<Optional

Parameter name> <Required parameter Value>


Parameter name> <Optional Parameter Value>]
Switch Parameter>]
Parameter Name>] <Required parameter Value>

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 47 of 361

Exercise 2: Command Aliases


In the previous exercise, the full verb-noun name was used when calling commands. Using
aliases, PowerShell provides the ability to create alternate names for any command.
Note: Aliases execute the underlying command using a different name.

There are two types of built-in aliases: Transitional and Convenience.


Transitional aliases: Transitional aliases were created to assist users migrating from
cmd.exe or UNIX/Linux shells to PowerShell. For example, the cmd.exe dir command lists
files and folders in the current directory. In UNIX/Linux shells, the same operation is
achieved using the ls command. PowerShell implements two transitional aliases for its
equivalent directory listing Cmdlet, Get-ChildItem. The following commands both execute
Get-ChildItem.
dir
ls

Convenience aliases: Convenience aliases are, as the name suggests, for convenience. For
example, Get-ChildItem has a convenience alias of gci, which saves the time required to type
the complete command name.
gci

Note: By default, PowerShell 2.0 has 137 aliases. The majority can be re-assigned to
point to a different command or deleted entirely, although they will be re-populated
when a new console or ISE session is established.

Task 1: Find Different Alias Commands


1. Find all the *-Alias commands using either of the methods below:
Get-Command Name *alias
Get-Command Noun alias

You will see five Cmdlets that can be used to manipulate aliases. The most useful of
which are Get-Alias, New-Alias and Set-Alias.
a. The Get-Alias Cmdlet is used to list all aliases.
Get-Alias

b. New-Alias allows you to create new aliases for a Cmdlet, Function or executable file.
The -Name parameter argument specifies the name of the new alias and the -Value
parameter specifies the command to alias.
New-Alias Name gp Value Get-Process

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 48 of 361

c. The Set-Alias Cmdlet can point an existing alias to a different command.


Set-Alias Name gp Value Get-PSProvider

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 49 of 361

Exercise 3: The Object-based Shell


Traditionally, the Windows command console and UNIX shells process data in the form of
strings. While this is a common way to represent data, it is not easy to extract and manipulate
the data. Character sequences need to be found using regular expressions or line/column
numbers and converted into the required string format for another command to process.
In contrast, PowerShell is an object-based shell built on the .NET framework. Objects are a
mechanism to store and manipulate data in a structured way. Data does not have to be
extracted from strings and can be accessed using a simple naming convention.
Note: PowerShells language is based on a POSIX standard shell (IEEE Spec.
1003.2), which itself is based on the UNIX Bourne Shell (Windows PowerShell in
Action Second Edition, Manning Press 2011 by Bruce Payette).

What is an Object?
Objects are all around us. A car is an object with a collection of separate parts, such as a
steering wheel, accelerator pedal and brakes. To drive the car, we can use the parts to steer,
accelerate and slow/stop the vehicle. We can now divide the car (object) into two distinct
concepts.

A collection of parts

Uses of the parts to change the cars behavior

Now, apply this object model to the Windows Operating System.


A Windows Service object has a collection of parts called Properties. Properties represent
the state of a service, such as the service name and status. The service status can be changed
by using object Methods. Object Methods allow you to start or stop a service. Collectively,
properties and methods are called object Members.
Members

Properties

Methods

Service Name

Start()

Status

Stop()

Note: Method names can be easily distinguished from property names as they are
always appended with a pair of smooth brackets ().

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 50 of 361

Task 1: List Object Information (Get-Member Cmdlet)


The .NET object framework is self-descriptive. All objects hold information that describes
their structure. You can interrogate any .NET object and list its properties and methods within
PowerShell without needing to refer to the online MSDN Class Library.
You can achieve this by passing the object through the pipeline, to the Get-Member Cmdlet.
Pipeline operations will be covered in detail in another lesson.
1. Get a list of process objects using the Get-Service Cmdlet and pipe them to the GetMember Cmdlet.
This will list the members (properties & methods) of this type of object.
Get-Service | Get-Member

2. Alternatively, you can choose not to use the pipeline and employ the Get-Member
Cmdlets InputObject parameter. This command however lists the members of the
collectin of pipeline data as a whole, rather than the individual items in the collection.
Get-Member InputObject (Get-Service)

The top of the output lists the type name of the object(s). In the first case when piping to
Ger-Member, you can see it is a System.ServiceProcess.ServiceController type of object.
TypeName: System.ServiceProcess.ServiceController

The next piece of information displayed is the collection of members (properties and
methods). The output below displays three columns of member information: the name,
membertype and definition.
Name
MemberType
------------Name
AliasProperty
RequiredServices
AliasProperty
Disposed
Event
Close
Method
Continue
Method
CreateObjRef
Method
Dispose
Method
Equals
Method
ExecuteCommand
Method
GetHashCode
Method
GetLifetimeService
Method
GetType
Method
InitializeLifetimeService Method
Pause
Method
Refresh
Method
Start
Method
Stop
Method
ToString
Method
WaitForStatus
Method
CanPauseAndContinue Property
CanShutdown
Property
CanStop
Property
Container
Property

Microsoft | Services

Definition
---------Name = ServiceName
RequiredServices = ServicesDependedOn
System.EventHandler Disposed(System.Object,
System.Void Close()
System.Void Continue()
System.Runtime.Remoting.ObjRef
System.Void Dispose()
bool Equals(System.Object obj)
System.Void ExecuteCommand(int command)
int GetHashCode()
System.Object GetLifetimeService()
type GetType()
System.Object InitializeLifetimeService()
System.Void Pause()
System.Void Refresh()
System.Void Start(), System.Void
System.Void Stop()
string ToString()
System.Void
System.Boolean CanPauseAndContinue {get;}
System.Boolean CanShutdown {get;}
System.Boolean CanStop {get;}
System.ComponentModel.IContainer Container

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 51 of 361

DependentServices
DisplayName
MachineName
ServiceHandle
ServiceName
ServicesDependedOn
ServiceType
Site
Status

Property
Property
Property
Property
Property
Property
Property
Property
Property

System.ServiceProcess.ServiceController[]
System.String DisplayName {get;set;}
System.String MachineName {get;set;}
System.Runtime.InteropServices.SafeHandle
System.String ServiceName {get;set;}
System.ServiceProcess.ServiceController[]
System.ServiceProcess.ServiceType
System.ComponentModel.ISite Site

3. The PowerShell code below returns the number of members that a


System.ServiceProcess.ServiceController object contains.
Note: Pipeline operations will be covered in more detail in the next lesson).

You can see that there are 32 members of a System.ServiceProcess.ServiceController


object.
Get-Service | Get-Member | Measure-Object -Property MemberType
Count
Average
Sum
Maximum
Minimum
Property

: 32
:
:
:
:
: MemberType

4. It is possible to shorten the output from this Cmdlet by listing only the properties.
Get-Service | Get-Member MemberType property

5. It is also possible to shorten the output by listing only the methods.


Get-Service | Get-Member MemberType method

6. Now that you have uncovered the objects members, you can use them to access state
information using properties and manipulate the object using methods.

Task 2: Access Object Members


To access information stored in object properties or execute object methods, the dot (.)
character is used to separate the object name from the member name. This is referred to as
dot-notation.
1. Select a single service object by filtering the output of the Get-Service Cmdlet using the
Name parameter and assign it to a variable.
$ALGService = Get-Service Name alg

2. Type the variable name to confirm that you have referenced the correct service.
By default, three properties of the service object are displayed: Status, Name and
DisplayName.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 52 of 361

$ALGService
Status
-----Running

Name
---ALG

DisplayName
----------Application Layer Gateway Service

3. Type a dot (.) character directly after the variable name and repeatedly press the Tab key.
The member names for this object type will be displayed one after the other.
4. Press Enter to display the information stored in one of the properties.
$ALGService.DisplayName
Application Layer Gateway Service

5. Type the variable name again, followed by a dot, and type Start(). Press Enter.
Note: Be sure to append smooth brackets () after the method name.
$ALGService.Start()

6. Type the variable name to view the service status.


Note that the status is still stopped. This is because the state of the service was saved at
the instant you assigned it to a variable in step 1. Following the assignment, the state has
not been updated.
7. To update the status property, execute the objects Refresh() method.
$ALGService.Refresh()

8. The status property should now display Running.


$ALGService
Status
-----Running

Name
---ALG

DisplayName
----------Application Layer Gateway Service

9. Lets see another example of accessing object members. Assign a string to a variable and
pass it through the pipeline to Get-Member to discover the string objects members.
Alternatively, you can use the alias for Get-Member (gm).
$strMyName = My name is Chris
$strMyName | Get-Member

10. You can also just pipe the string directly to the Get-Member Cmdlet. Both commands in
steps 8 and 9 produce the same output.
My name is Chris | Get-Member

11. The object type name returned is System.String. This type has 2 properties and 32
methods. The length property stores the number of characters in the string. In this case,
the string consists of 16 characters.
$strMyName.length
16

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 53 of 361

Alternatively, call the property using the string, rather than the variable. Again, both
commands produce identical output.
(My name is Chris).length
16

Note: Even though the parenthesis are not required above, it makes sense to have
them since it applies to other types of commands where this is not possible without
parenthesis.

Try calling a few of the object methods.


o

The Split() method splits the string on every occurrence of a space character and
returns an array.
$strMyName.Split()
My
name
is
chris

The Substring() method returns a part of the string. This method requires input
parameters to be provided within the parenthesis to represent the startIndex.
$strMyName.Substring(11)
Chris

The Replace() method replaces a substring of characters with another. This


method requires two input parameters:

The string to find

The string to replace it with

$strMyName.Replace("Chris","John")
My name is John

Note: The $strMyName variable is never modified by any of the methods and still
contains the original string.

Task 3: Use the *-Object Cmdlets


PowerShell has a group of Cmdlets that can manipulate any type of object. This Cmdlet is
typically used in a pipeline operation. Pipeline operations will be covered in detail in another
lesson.
1. List the *-Object Cmdlets.
Get-Command noun Object
CommandType Name
----------- ----

Microsoft | Services

Definition
----------

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 54 of 361

Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet

Compare-Object
ForEach-Object
Group-Object
Measure-Object
New-Object
Select-Object
Sort-Object
Tee-Object
Where-Object

Compare-Object [-ReferenceObject
ForEach-Object [-Process] <Scrip
Group-Object [[-Property] <Objec
Measure-Object [[-Property] <Str
New-Object [-TypeName] <String>
Select-Object [[-Property] <Obje
Sort-Object [[-Property] <Object
Tee-Object [-FilePath] <String>
Where-Object [-FilterScript] <Sc

2. Use the Sort-Object Cmdlet to sort a list of file and folders by their lastwritetime
property.
Get-ChildItem Path C:\Windows | Sort-Object Property LastWriteTime

3. Find Process objects with more than 500 open handles using the Where-Object Cmdlet.
Get-Process | Where-Object {$_.handles gt 500}

4. Return the total file size of a directory in KB.


Get-ChildItem Path C:\Program Files Recurse | Measure-Object Property length
-Sum

Task 4: Add Object Members


PowerShell allows you to add user-defined members to existing objects.
For example, you want to display the number of threads within a process object. The AddMember Cmdlet can be used to add a new property in which to store information.
1. To add a new property, return a process object using the Get-Process Cmdlet and assign
it to a variable.
$process = Get-Process -Name lsass

2. Confirm that the Process objects Threads property contains a list of thread objects.
$process.Threads

Since the Threads property is an array object, it has a count property that stores the
number of thread objects contained within it.
3. Use the Add-Member Cmdlet to add a new scriptproperty called ThreadCount to the
process object. Note that the InputObject parameter is used to supply the object AddMember operates on.
The Value property argument is contained in a set of curly brackets '{}'. This is called a
scriptblock and can contain any PowerShell code. The $this variable refers to the current
object instance stored in the $process variable.
Add-Member InputObject $process -MemberType scriptproperty -Name ThreadCount `
Value {$this.Threads.Count} -PassThru

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 55 of 361

4. Access the new property to display the number of threads running in this particular
process.
$process.ThreadCount
15

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 56 of 361

Exercise 4: The .NET Object Model


The .NET (pronounced dot net) framework consists of a library of code that enables
interaction with many aspects of the Windows Operating system and an environment in
which the code runs. The separation of the runtime environment (Common Language
Runtime) and the underlying Windows operating system ensures .NET code is unable to
directly compromise operating system security and stability.

.NET Assemblies, Namespaces and Types


The .NET Class Library is organized into Assemblies, Namespaces and Types.
An assembly is a collection of related namespaces and usually, although not always, maps to
a single *.dll file stored on the local machines hard disk. A namespace contains a collection
of related types.
Namespace and type names are separated by a dot (.), in the same way object members are
separated from an object name. The top of the .NET framework hierarchy is called System.
The rest of the hierarchy is organized into namespaces and types under this root namespace.
Sometimes it is not obvious which part is the namespace and which is the type.

Namespace

System.String

Type

Namespace

System.DirectoryServices.DirectoryEntry

Type
Note: Types are also called classes. You will probably see the two names used
interchangeably.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 57 of 361

Types and Objects


The car analogy (used previously) can be used again to explain the relationship between types
and objects.
Consider a factory that manufactures a single model of a car. The cars are all based on the
same design, although many instances of the model can be produced, each with different
characteristics, such as the engine size, color, or internal trim.
Types are factories that create instances of a particular model of object. A type defines the
number and implementation of members (properties and methods). Many objects can be
created from a single type, but are distinct instances of that type.
In a nutshell, an object is an instance of a type.

Task 1: Create new Objects Using the New-Object Cmdlet


As you have seen, PowerShell will automatically create a new object during assignment of a
value to a variable.
1. Assign a string to a variable
$strHello = Hello World

2. Use the GetType() method, which is included on every .NET object by default, to
discover the type of object PowerShell created.
PS C:\ > $strHello.GetType()
IsPublic IsSerial Name
-------- -------- ---True
True
String

BaseType
-------System.Object

3. We can view the fully qualified name of the type by accessing the FullName property of
the type object.
$strHello.GetType().Fullname
System.String

4. You can use the New-Object Cmdlet to create a new instance of a type. In the next
example, you will create a new System.String object using this method, although it
produces exactly the same result as variable assignment shown above.
$strHello2 = New-Object TypeName System.String(Hello World)

5. New-Object allows us to create any object in the .NET framework. For example, creating
a directory searcher allows us to query Active Directory
Create a System.Directoryservices.Directorysearcher object
$objsearcher = new-object system.directoryservices.directorysearcher

6. Execute the findone method to find the first object in Active Directory using a filter of *
$objsearcher.findone()

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 58 of 361

You will now see an Active Directory entry object.


7. Sending an ICMP packet, commonly known as a ping, is a simple process.
Create a System.Net.Networkinformation.Ping object
$ping = New-Object TypeName System.Net.Networkinformation.Ping

8. Use the objects Send() method to send a ping to a specific hostname or IP address.
$ping.Send(localhost)

Object Models
The .NET framework is not the only object model PowerShell can use.
The Component Object Model (COM) and Windows Management Instrumentation (WMI)
technologies are also directly supported.

Task 2: Component Object Model (COM)


COM is a Microsoft technology that allows type libraries to be created. These type libraries
can be accessed by many different languages. Before the advent of COM, a different version
of a type would need to be created for each language accessing it. COM Object type names
are registered in the HKEY_CLASSES_ROOT registry hive using the regsvr32.exe utility.
1. Use the New-Object Cmdlet to create a new COM object instance.
The COM object type name is specified as an argument to the -ComObject parameter.
$objWSH = New-Object ComObject WScript.Shell

2. To list the members of the new COM object, simply pipe the variable to Get-Member.
$objWSH | Get-Member

Note: The type name is in the form of a GUID.


Typename: System.__ComObject#{41904400-be18-11d3-a28b-00104bd35090}

3. Use dot notation to access properties and execute methods.


Accessing properties and executing methods is achieved in exactly the same way as
a .NET object.
$objWSH.CurrentDirectory
$objWSH.Popup("New Message",$null,"New Dialog Box")

Note: In practice the popup method of the WSH object should not be used. Instead
the .Net framework type of system.windows.forms.messagebox should be used.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 59 of 361

Task 3: Windows Management Instrumentation (WMI)


WMI is Microsofts implementation of an industry standard system management object
model. WMI allows management of software and hardware objects. It is a languageindependent distributed COM (DCOM) application and can be accessed by a number of
scripting and programming interfaces.
The WMI object model is organized into namespaces that logically group objects of a similar
technology, organized below a root namespace. Each namespace contains many types
(classes) that can be instantiated as objects.
WMI can simply be accessed in PowerShell through a single Cmdlet, called GetWMIObject.
1. Specify the -list parameter to display all the classes within the CIMv2 namespace.
Get-WMIObject namespace root\CIMv2 list

2. Type one of the class names as the argument to the -class parameter to list its information.
Store the object in a variable.
$objBIOS = Get-WMIObject namespace root\CIMv2 class Win32_BIOS

3. List the member information (properties and methods) for your chosen class using GetMember.
$objBIOS | Get-Member

4. Select a property and access its information.


$objBIOS.Manufacturer

Many WMI objects allow changing the objects state through object methods. The
Win32_OperatingSystem class allows us to reboot the OS locally or remotely.
Note: On Windows Vista and above Operating Systems, the PowerShell console must
be run as an administrator and the shutdown privilege enabled.

5. Store a reference to the Win32_OperatingSystem class in the $objOS variable.


$objOS = Get-WMIObject class Win32_OperatingSystem

6. Request the correct privilege if on using a Windows Vista or above OS.


$objOS.psbase.Scope.Options.EnablePrivileges = $true # needed for Vista & above OS

7. Call the Reboot() method on the object.


$objOS.Reboot()

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 60 of 361

Lesson 2 Hands-On : Commands and objects


Objectives
The objectives for this lab are:

Exercise 1: Working with PowerShell command help & syntax


Exercise 2: Discovering object members

Prerequisites

The lab requires a windows 7 client running in a domain environment.

Estimated time to complete this lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 61 of 361

Exercise 1: PowerShell Commands


Objectives
In this exercise, you will perform the following operations to complete the specified task:

Discover PowerShell commands

Investigate command syntax & usage

Estimated time to complete this lab


10 minutes

Scenario
As we have seen, PowerShell contains a large number of built-in commands, called cmdlets. In this
exercise we will find cmdlets and discover their syntax in order to complete a task.

Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Open Windows PowerShell Session


On the windows task bar locate the

icon. Click on this icon.

The PowerShell window will open.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 62 of 361

Tasks to Perform:
The objective of this exercise is to measure the total size of all .txt files in C:\Program Files
and all its subfolders.
1. From the PowerShell console, execute the following command. In PowerShell v2.0, the
commandType parameter is required to include only cmdlet objects in the output. By
default this command returns cmdlets, functions and aliases.
Get-Command commandType cmdlet

This will return a list of the default PowerShell cmdlets. While this list is comprehensive, it is
also rather large.
2. Lets reduce the size of the list by using one of the Get-Command cmdlets parameters to
filter the results. To do this we must first discover how to use Get-Command, by
employing the Get-Help cmdlet, to view the associated help file.
Get-Help name Get-Command

As you can see, the output is fairly general. It may be more help to only list the parameters
available on this cmdlet.
3. Modify the previous command to include Parameter, followed by a wildcard (*)
character, to list all the parameters for the cmdlet.
Get-Help Name Get-Command Parameter *

4. The output gives much more detail about each parameter. As our first objective is to find
the cmdlets we need to complete the task, use the Name, -Verb and Noun parameters
to search for cmdlets by full name, verb and noun. Specifying keywords and wildcard
characters will allow Get-Command to filter the cmdlet list.
The task states that we must measure the total size of files in a folder and its subfolders. To
complete the objective, we must first get a list of file & folder objects. The Get-* cmdlets are
often used as the first cmdlet in a PowerShell pipeline, as they return a list of objects of a
specific type.
Get-Command -commandType cmdlet get*
5. The list is much shorter than the output of step 1. The cmdlet we require is Get-ChildItem,
near the top of the list. Familiarize yourself with this cmdlets parameters and syntax
using Get-Help.
Get-Help Name Get-Childitem Parameter *

Another great way to discover cmdlet syntax and usage is by using Get-Helps Example
switch parameter.
Get-Help Name Get-ChildItem Example

6. Use the help to decide which parameters are needed to list all text files beneath the path
C:\Program Files. Note that the path (C:\Program Files) contains a space character, so it
must be enclosed within single or double quotes.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 63 of 361

Get-ChildItem Path C:\Program Files Recurse Filter *.txt

7. The command does return all .txt files and folders beneath the specified path. The
recurse switch parameter (a parameter that doesnt require an argument), ensures that all
subfolders are searched & the Filter parameters argument constrains the search to files
with the extension txt.
8. The previous steps complete the collection of file and folder objects. Next, we need to
calculate their total size. To do this we require a cmdlet that can measure the length
property of all file objects returned (folders do not have a length property & therefore
dont directly have an impact on disk space, other than their entries in the Master File
Table).
Use Get-Command to search for cmdlets with the keyword Measure. Note that this time
we arent sure if the noun or verb part of the cmdlet name contains the text, so we use the
name parameter to search the full name. Surrounding the text with wild-card characters
ensures all possible matches are returned.
Get-Command CommandType cmdlet Name *Measure*

9. Fortunately only 2 cmdlets contain the word measure. To decide which one to use, have
a look at their associated help files. Instead of using the Get-Help cmdlet, try using the
shortcut to displaying the default help for a cmdlet, the -? Switch parameter.
Measure-Object -?

10. The Measure-Object cmdlet is suitable to complete this task as it calculates the
numeric properties of objects Use Get-Helps Detailed, -Example and Parameter
parameters to discover more information about the commands syntax & usage.
Get-Help Measure-Object Detailed
Get-Help Measure-Object Example
Get-Help Measure-Object Parameter *

Measure-Object accepts pipeline object input and allows the property of interest to be
specified using its Property parameter. The sum switch parameter stores a running total
of the file sizes.
Get-service | Measure-Object

11. The length property of a file object stores its size on disk, in bytes. A simple pipeline
operation (pipelines are covered in detail in the next module) is all that is needed to pass
the filtered list of .txt files to Measure-Object.
Get-ChildItem path C:\Program Files Filter *.txt Recurse |
Measure-Object Property length Sum

12. The Measure-Object cmdlet returns a single object containing its results, therefore we are
able to access its Sum property directly and perform further formatting. Such as
displaying the total file size in Megabytes.
To do this, enclose the previous pipeline command in smooth parentheses and use a dot .
to access the objects Sum property.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 64 of 361

Finally, use the division operator (/) and MB constant to convert the Sum propertys
byte result to Megabytes.
(Get-ChildItem path C:\Program Files Filter *.txt Recurse |
Measure-Object Property length Sum).sum / 1MB

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 65 of 361

Exercise 2: Discovering Object Members


Objectives
In this exercise, you will:

Expose object members using the Get-Member cmdlet.

Estimated time to complete this lab


10 minutes

Scenario
In this exercise we will learn how to discover the members of existing objects and create new .NET
object instances.

Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Open Windows PowerShell Session


On the windows task bar locate the

icon. Click on this icon.

The PowerShell window will open.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 66 of 361

Tasks to Perform:
Since everything we will work with in PowerShell is an object, it is crucial to be able to
discover the various members (properties and methods) of any object.
We will take the common administrative task of working with files and folders as an example
of how to discover and use object members.
1. Use the Get-ChildItem cmdlet to list file and folder objects from C:\Windows and
pipeline them to the Get-Member cmdlet in order to view the type of objects returned.
Get-ChildItem path C:\Windows | get-Member

2. From the output we can see that two different types of object exist in the file system,
System.IO.DirectoryInfo and System.IO.FileInfo objects.
Each of these object types contain a large number of members. Execute the command
above, but this time, include Get-Members MemberType parameter & specify the
argument property. The output now only lists the object properties.
Get-ChildItem Path C:\Windows | Get-Member MemberType property

3. The LastWriteTime property can be seen in the listing. This property contains a date
object that stores the last time the file or folder was modified.
4. How would you list only object methods?
5. Next, we will create a pipeline command to filter all files and folders modified over 60
days ago. To do this we will need to create an object that represents a date. Use the GetDate cmdlet to create a new date object and save a reference to this object in a variable.
$Date = Get-Date

6. Using the Get-Member cmdlet we can view the members of the date object referenced by
the $Date variable.
$Date | Get-Member

7. One member that can be seen in the output is the AddDays() method. By supplying an
input parameter to the method we can produce a modified date.
$Date.AddDays(-60)

8. We can now use the members found on the file, folder and date objects to perform a
pipeline operation to determine the files and folders modified over 60 days previously.
The pipeline operation performs the following operations.
i)
ii)
iii)

Lists all file and folder objects in the C:\Windows folder.


Pipeline the objects to the Where-Object cmdlet.
Determine whether the current file or folder objects LastWriteTime property is
greater than the current date, minus 60 days.

Get-ChildItem Path C:\Windows |

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 67 of 361

Where-Object {$_.LastWriteTime

Microsoft | Services

lt

$Date.AddDays(-60)}

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 68 of 361

Exercise 3: Creating Object Instances


Objectives
In this exercise, you will:

Create a new .NET object instance.

Create a new COM object instance

Estimated time to complete this lab


10 minutes

Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Open Windows PowerShell Session


On the windows task bar locate the

icon. Click on this icon.

The PowerShell window will open.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 69 of 361

Tasks to perform:
In this exercise we will create a new TcpClient object and use it to check connectivity to a
TCP port number on a remote machine.
1. First we must create an instance of the TcpClient class and save a reference to it in a
variable. To do this, specify the .NET class name of the object as an argument to the
New-Object cmdlets TypeName property.
The full name of the class is System.Net.Sockets.TcpClient.
$tcpClient = New-Object TypeName System.Net.Sockets.TcpClient

2. Use Get-Member to see what members exist on this type of object.


$tcpClient | Get-Member

3. One of the members listed is the Connect() method. An easy way to view the input
parameters for a method is to type the method name omitting the parentheses.
$tcpClient.Connect

Four different numbers and combinations of input parameters can be specified for this
particular method This method is referred to as having four overloads.
The overload we are going to use (the first in the above list) requires two objects, a string
that represents the hostname of the remote machine and an Integer that stores the port
name on which we wish to connect.
4. Try executing the Connect() method against SYDDC01 on port 80.
$tcpClient.Connect(SYDDC01,80)

5. If no error was returned, confirm that the connection is open using the connected property.
The value True should be returned
$tcpClient.Connected

6. Use the Close() method to close the TCP socket connection and dispose of the TCPClient
object.
$tcpClient.Close()

In the next exercise we will create a COM object. Thousands of COM objects ProgID
identifiers are listed in the Operating System registry under HKEY_CLASSES_ROOT.
We will create an instance of the InternetExplorer.Application COM class, which allows
Microsofts Internet Explorer browser to be manipulated programmatically.
Note: The next task requires internet access, and should therefore be performed on
the student host machine.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 70 of 361

1. Creating a COM object instance is also achieved using the New-Object cmdlet, although
the ComObject parameter is used, instead of the TypeName parameter.
$ie = New-Object ComObject InternetExplorer.Application

2. Get-Member can be used to view the objects members in exactly the same manner
as .NET objects.
$ie | Get-Member

3. The Navigate2() method opens the URL specified in the methods input parameter.
$ie.Navigate2(http://www.microsoft.com)

4. At this point, the Internet Explorer window is not visible. Using Get-Member, locate the
member name that allows the window to appear. What data type does it accept?
5. Next, set the Visible property to the value $true.
$ie.Visible = $true

6. The Internet Explorer should now be visible. How would you close the Internet Explorer
window using PowerShell?

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 71 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 3: PowerShell Pipeline
Student Lab Manual

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 72 of 361

Lesson 3 Demonstration : Pipeline


Introduction
This lab introduces the PowerShell pipeline and covers the fundamental aspects of it
including:

Input and output

Flow control

Grouping

Sorting

Formatting

Various operators used when piping commands together

This module also discusses the pipeline variable ($_), covering when and how it is used.

Objectives
After completing this lab, you will be able to:

Understand the fundamental operators

Understand pipeline usage, syntax, and the pipeline variable

Display, Filter, Sort, and Group Cmdlet output via the pipeline

Control pipeline input and output

Prerequisites
To complete this lab, you need:

A Windows 7 workstation logged onto with administrator credentials

Estimated Time to Complete this Lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 73 of 361

Exercise 1: Understand the Fundamental Operators


Objectives
In this exercise, you will:

Learn comparison operators

Discover regular expression usage

Learn logical operators

Scenario
PowerShell consists of many different operators:

Arithmetic

Assignment

Comparison

Logical

Redirection

Substring

Type

Unary

Special

In this lesson, you will understand comparison and logical operators, which you will
commonly encounter while working with the pipeline.
Comparison operators are used to:

Compare values such as text and numbers

Provide a mechanism for testing conditions such as during a call to the Where-Object
Cmdlet

There are 13 different comparison operators. Some test for simple equality while others work
with sets or special matching situations.
Logical operators allow you to join multiple operations to check for compound conditions
being true or false. There are five logical operators you will work with, two of which serve
the same purpose.

Log on to VM Environment
Log on to the Windows 7 Enterprise client

Task 1: Test Equality


To test if two values are equal to or not equal to each other, you can use the eq or ne
operators respectively. These operators, like all comparison operators, are case-insensitive by
default.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 74 of 361

1. Open the PowerShell console or ISE and type the following command:
PowerShell eq powershell

This command will return a value of True indicating that these two string values are
equal to each other.
2. You can also test if two values are not equal by running the following command:
POWERSHELL ne powershell

This command returns a value of False since PowerShell is case-insensitive and,


irrespective of the case, by default two strings of the same character combination and
order will be the same.
3. If you want PowerShell to perform a case-sensitive test of equality, you can add a c
before the operator you are using.
PowerShell ceq powershell

This will return a value of False since the strings have different casing. This will work
with any comparison operator, not just eq and ne.
4. PowerShell can be made to explicitly do a case-insensitive comparison, which can help
readability in scripts in certain cases. This is done by using an i instead of a c.
PowerShell ieq powershell

This will return True once again since an insensitive comparison was explicitly used.
5. Testing equality does not stop with -eq and -ne. You may also need to know whether
something is less than, greater than, and so on. When working with numbers, these
operations function exactly as you would expect; the following commands:
4
3
3
7

gt
ge
lt
le

4
3
7
4

The commands above will return the values False, True, True, False, respectively, for
tests of greater than, greater than or equal to, less than, and less than or equal to
operators.
6. You can do the same thing with strings as well.
Reed gt Read
k lt g
powershell le POWERSHELL
user cge USER

These commands will return the values True, False, True, and False, respectively. When
comparing string values, PowerShell uses the Compare method built into the String type.
Therefore, in a case-sensitive comparison, u is considered less than U.
7. It is interesting to note that you can use arrays when testing for equality. When you do
this, you will get more than a simple True or False return value.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 75 of 361

foo,bar,baz,qux eq foo
fizz,buzz,bang -ne buzz
one,two,three eq four

In the example shown above:

Instead of returning a simple True, the first command returns foo indicating that it
found that value to be equal to the one being tested against

The second command returns an array containing fizz and bang indicating that it
found those values to be not-equal to buzz

The last command returns no data because nothing in the array is equal to four

Task 2: Further Tests with Arrays


While equality is easily tested against an array and will return the appropriate set of values,
sometimes only a True or False value is required that can be used simply in a conditional
statement.
1. To check if a specific value is contained within an array, you can use the -contains
operator, returning True if the specified value is found, otherwise false.
foo,bar,baz,qux contains bar
one,two,three contains four

In the example shown above:

The first command will return a value of True since bar is contained within the
array

The second command will return False since four is not contained within the array

2. To check if a value is not contained within an array, you can simply change the operator
to -notcontains instead. Use the same data as our previous example, but with the new
operator.
foo,bar,baz,qux notcontains bar
one,two,three notcontains four

This will then return False for the first command and True for the second.

Task 3: Wildcard and Regular Expression Tests


Checking for a specific value being equal to another is not always enough to confirm if you
are dealing with the right data. Sometimes you will need to match a string based on only a
part of it. For example, looking at a list of usernames and only returning those that begin with
the letter P.
PowerShell allows you to use basic wildcards through the -like and -notlike operators, and
allows you access to regular expressions through -match and -notmatch.
1. Wildcard characters allow you to represent more than a single character when matching.
Dog like D*
Dug like D[ou]g

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 76 of 361

Dig notlike D?g


Doug like D[a-z]g

In the example shown above:

The first returns true because the * character is a wildcard that matches zero or
more characters of any kind

The second returns true because the square brackets denote a group of characters to
match a single time, in this case o or u

The third returns false because although you allow any single character with the ?
wildcard character you are using the notlike operator

The fourth also returns false but this time it uses a range wildcard to match any single
letter from a to z, but here you have two characters in the middle

2. Just like other comparison operators, the like and notlike operators can be forced to be
case sensitive by adding a c to the operator name
Cat clike C*
Cat clike c[au]t
curl clike c[au]*

These three commands will return true, false, and true, respectively.

Logical Operators
In order to combine a number of different comparison operators, you need to use logical
operators to make compound statements. The logical operators you can use are -and, -or, -xor,
and -not. There is one additional operator that is available that does the same thing as the -not
operator, but it is only a single character "!" (exclamation mark).
The -and, -or, and -xor operators are binary operators. This means that they operate on two
statements, allow you to combine them, and get a single statement output. Each operator has
a left and a right side statement which are joined, and either side can also be another logical
statement.
The following truth table shows the logical functionality of each operator, where p represents
the statement on the left side of the operator and q represents the statement on the right side:
p

-and

-or

-xor

$true

$true

$true

$true

$false

$true

$false

$false

$true

$true

$false

$true

$false

$true

$true

$false

$false

$false

$false

$false

The -not and ! operators are simpler because they are unary operators they only operate on
a single statement. So, instead of having a left and right side, you place the operator in front
of the statement you wish to negate.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 77 of 361

-not

$true

$false

$false

$false

$true

$true

Using these operators within PowerShell is quite simple. However, the order of operations is
a point to take note of, since the incorrect order can cause unexpected results. You can use
parenthesis to override the order of operations, forcing PowerShell to evaluate anything
within the parenthesis first.
(4 ge 8) and (5 lt 10)
! (4 eq 4)
-not $true xor $false
-not ($true xor $false)

Note: The about_Operator_Precedence help topic is not included with PowerShell 2.0
documentation however, it can be read via TechNet http://technet.microsoft.com/enus/library/ee681734.aspx

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 78 of 361

Exercise 2: Understand Pipeline usage, syntax, and the


pipeline variable
Objectives
In this exercise, you will:

Understand pipeline basics (usage and syntax)

Understand pipeline variable

Scenario
The pipeline allows a user to take a number of simple commands and string them together
into a single pipeline. In the previous exercises, you were writing statements for PowerShell
to evaluate. The evaluation of these statements produced an output.
The fact that these commands produce output without having to explicitly tell PowerShell to
do so ties in directly with the concept of the pipeline.
PowerShell will take an object on the pipeline and pass it from one command to the next until
there are no additional commands to pass through. When an object reaches the end of the
pipeline, PowerShell outputs it to the host.

Log on to VM Environment
Log on to the Windows 7 Enterprise client.

Task 1: Understand Pipeline Basics


1. Open the PowerShell console or ISE and type the following command.
Get-Process | Where { $_.WS gt 15MB } | Sort WS | FT property Id, Name, WS

The command above is a single pipeline made up of four commands that take the output
of the Get-Process command and pass it along the pipeline. Each command is separated
by a pipe | which sends the output from one command to the next.
2. One of the revolutionary aspects of PowerShell is that the pipeline passes objects rather
than the simple text data you see on the screen.
Get-Process

This command will output the list of running processes on the user's machine with eight
properties displayed for each process, including its ID and working set.
3. Now, take that data and pipe it into Format-Table to display other properties.
Get-Process | Format-Table ID, ProcessName, StartTime, MainWindowTitle -Autosize

Even though Get-Process by itself only displays six properties for each process, there is
more data that gets passed along the pipeline. In this case, you are sending process
objects to Format-Table, which then displays two properties: StartTime and
MainWindowTitle, which were previously unavailable.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 79 of 361

4. A more involved pipeline might look something like this:


Get-Process | Where { $_.WS -gt 15MB } | Sort WS | FT Id, Name, WS

As you can see, you can use more than a single pipe in a command to make it more useful.
Here, a few aliases are used to make the command fit on a single line, but the task
performed is passing objects along four different commands in the pipeline. The output of
each command is always passed from left to right along the pipeline.

Task 2: Understand the Pipeline Variable


You may have noticed in previous examples when using the Where-Object Cmdlet you had
a reference to $_. This is a special variable called the pipeline variable. The pipeline variable
is used to refer to the current object on the pipeline.
An interesting fact about the pipeline is that, when looking at the data returned by a Cmdlet
or function, objects are often returned one at a time. This operation is asynchronous in a way
because a Cmdlet does not necessarily need to complete processing before the output can be
passed on to the next command in the pipeline.

Get-Process

Where-Object
{ $_.WS -gt 50MB }

Sort-Object
-property WS

Format-Table
-property Id, Name, WS

Some Cmdlets however, do require all of the possible input before they can produce any
output, such as the case with Sort-Object. In the example above, Sort-Object needs to know
the working set of every process before it can sort them according to that property.
1. When piping data, usually things will show up very quickly, which can make it seem like
data gets sent along the pipeline instantly:
1..5
1..5 | Sort-Object -Descending

Here, you start by creating an array of numbers from one to five using the range operator
(..). Since there are no additional commands on the pipeline, PowerShell outputs those
numbers to the console. When you pipe that range of numbers to Sort-Object, it changes
the order of the numbers as they get passed along the pipeline.
2. Using the ForEach-Object Cmdlet, you can slow down the data being sent along the
pipeline.
1..5 | ForEach-Object { Start-Sleep 1; $_ }

The ForEach-Object Cmdlet instructs PowerShell to sleep, by using the Start-Sleep


Cmdlet, for one second before then passing each object along the pipeline.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 80 of 361

Here you can see the numbers one through five displays with a one-second delay between
each one. Each object gets passed along the pipeline and, in this case, it outputs them to
the console.
3. However, not every Cmdlet can process the pipeline data asynchronously.
1..5 | ForEach-Object { Start-Sleep 1; $_ } | Sort-Object -Descending

Here you see a 5 second delay before anything actually happens because Sort-Object
cannot process the data asynchronously. Sort-Object is a command that needs to receive
all of the pipeline data before it can decide what the appropriate sort will be. After the
initial delay, however, the numbers all appear almost instantly because Sort-Object
sends all of the data along the pipeline once it is finished processing.
4. To slow down the data as it is passed further along the pipeline, you can move the
ForEach-Object Cmdlet after the sort.
1..5 | Sort-Object Descending | ForEach-Object { Start-Sleep 1; $_ }

Now you can see that the data is sorted first, quickly, before it is slowed down in the
ForEach-Object loop before being output.
5. If you were to use the output of a Cmdlet rather than a range of numbers, you would see a
similar result.
Get-Process | Sort-Object Descending | ForEach-Object { Start-Sleep -m 250; $_ }

The process objects from Get-Process are passed along the pipeline one at a time. In this
example, you can see each running process with a 250 millisecond delay between each
one. In all the examples so far, you have been treating the pipeline variable as a single
unit. However, in reality there are more behind the scenes.
6. Consider the members available to each object output by Get-Process.
Get-Process | Get-Member

You can see that there are several properties available. The pipeline variable applies to
the entire object. In the case of Get-Member, it has to inspect each object to provide
feedback to the user about the available members, since not every object on the pipeline
will be of the same type. Get-Process contains the same type of object so all you see are
members of the System.Diagnostics.Process type.
7. Now, consider a directory.
Get-ChildItem C:\Windows | Get-Member

In this case, you can see that there are both System.IO.FileInfo and
System.IO.DirectoryInfo objects being passed along the pipeline.
8. Get-Member is another Cmdlet that processes data asynchronously.
Get-ChildItem C:\Windows\s*.*

When you run the command above, the Cmdlet returns directories before files in the list.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 81 of 361

9. You can add a delay to this command before sending it along the pipeline to Get-Member.
Get-ChildItem C:\Windows\s*.* | ForEach-Object {Start-Sleep 1; $_ } | Get-Member

Now you will see the type information come back slowly. This is because Get-Member
will only pass unique type information along the pipeline and, therefore, you have to wait
for each of the objects and their associated sleep command to occur.
10. What you have seen is that $_ refers to only a single object along the pipeline. However,
each object has individual members and the pipeline variable provides access to all of
them for each individual object.
Get-ChildItem C:\Windows\s*.* | ForEach-Object { $_.Name; $_.LastWriteTime }

Here you can see that the ForEach-Object Cmdlet allows you to access the name and
last write time for each object that is passed along the pipeline to it.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 82 of 361

Exercise 3: Filtering, Sorting, and Grouping data


Objectives
In this exercise, you will:

Control the display of pipeline objects

Filter pipeline objects

Sort and group pipeline objects

Scenario
There are a number of different Cmdlets that allow you to modify the order of data that is
passed along the pipeline. In this exercise, you will look at some of the most common
Cmdlets that are used in this process.
The Get-Process Cmdlet, for example, has parameters that allow you to control which
process objects are passed back along the pipeline. However, you may need to be more
restrictive of that data than the Cmdlet allows. There are also times where you may need to
display data that does not show by default or change the order of what is passed along the
pipeline.

Log on to VM Environment
Log on to the Windows 7 Enterprise client

Task 1: Controlling the Display of Pipeline Data


When working with objects on the pipeline, PowerShell typically only outputs the most
pertinent data to the console. This is controlled by some advanced functionality within
PowerShell in a number of configuration xml files that tell PowerShell how to handle data. If
you want to override this default display of data, there are a few options at your disposal.
1. The most basic method of controlling the properties that display for a given object is to
use the Select-Object Cmdlet.
Get-Process | Select-Object -property ID, Name, WS, MainWindowTitle
Get-ChildItem | Select Name, Length, LastWriteTime

Here you can see that the display returns different information than what is returned by
Get-Process and Get-ChildItem when run by themselves. Using the default property
parameter allows you to specify an array of properties to pass further along the pipeline.
In the second command you can use the built-in alias: Select.
2. Sometimes you may want to return more detailed information than a basic property value.
In the previous Get-ChildItem example, you selected the length property, which is used
for file size in bytes. If you want to change it so that it displays in megabytes, you can
provide a custom property through a hash table.
gci | Select Name, @{Name=Size(MB);Expression={[Math]::Round($_.Length/1MB, 2)}}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 83 of 361

The hash table that you provide has two key/value pairs.

The first is called Name and specified the name of the property that will be displayed.
This will show as the column heading in table format or the label in list format.

The second value is an expression provided as a code block, which uses the Math
class to round the file size to two decimal places after dividing by 1MB.

3. Select-Object allows you to change the properties that are returned as well as the number
of objects that are passed along.
Get-Process | Select ID, Name, WS -First 5
Get-Process | Select ID, Name, WS -Last 10

In the example above, the Select-Object Cmdlet is instructed to only select the first 5
objects from the pipeline (in the first example) or the last 10 objects (in the second
example).
4. There is also a parameter called Index, which will return only the nth item from the
pipeline.
Get-Process | Select -Index 10

Depending on what applications your system is running, you could see a wide variety of
processes returned here. However, it will only be a single process, and if you look at the
full list that Get-Process returns by itself, you will see that it is the 11th process on the list.
It is the 11th item from the list because the Index is 0-based, meaning our first item is
index 0, second item is index 1, and so on. This concept ties in with arrays as well, which
are also 0-based in PowerShell.
5. It is important to note that Select-Object modifies the objects being passed along the
pipeline.
Get-Process | Select ID, Name, WS | Get-Member

When you pass a Select-Object to Get-Member, the data changes and you no longer
have a full representation of the object that was passed into Select-Object. In the case
above, you will notice that all of the extra properties that were not included in the
Property parameter are now missing from Get-Members output. Any other properties
are now unavailable to any remaining commands on the pipeline. If you were to try sort
your output after this by the CPU utilization (which was not included in the Select) you
would not see the order change because the CPU property is missing.
6. In addition to Select-Object, there are a few other Cmdlets that are used for controlling
the properties that are displayed on the screen: Format-List and Format-Table. These
Cmdlets both allow you to specify the properties.
Get-Process | Format-List -Property ID, Name
Get-Process | FL ID, Name, CPU, WS

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 84 of 361

The Format-List Cmdlet simply takes the data and converts it into a format where your
key and value pair are listed horizontally. The second command uses the built-in alias for
Format-List: FL
7. Typically, objects get output to the screen in a tabular format based on the configuration
files mentioned earlier. However, sometimes that output will default to a list format.
When it does, you can use Format-Table to force it to display as a table.
Get-Service | Format-Table -Property Name, Status
Get-Service | FT Name, Status -AutoSize

The Format-Table Cmdlet also has an autosize parameter, which controls how much of
the screen is taken up by the output. PowerShell attempts to determine the most
appropriate display format when using this parameter. The second example uses the builtin alias for Format-Table: FT.
8. Like the Select-Object Cmdlet, Format-Table and Format-List also change the data
that is passed along the pipeline. However, these Format commands do it drastically.
Get-Process | FL ID, Name, CPU, WS | Get-Member

What you can see from the Get-Member output is that you have a number of different
objects that are being passed along the pipeline by the Format-List command. This
change in the object makes it impossible to access any of these properties again.
9. You can use a Sort-Object Cmdlet to order data after a Select-Object Cmdlet, but not
with Format-List or Format-Table.
Get-Process | Select ID, Name, CPU, WS | Sort-Object WS
Get-Process | FL ID, Name, CPU, WS | Sort-Object WS

The first command will properly sort the data. This is not a recommended format for
writing this command. The Select-Object Cmdlet is still changing the data so if you were
to try to sort by virtual memory size (VM) instead of working set (WS) no sorting would
actually take place, since the VM property is gone.
The second command with Format-List is more drastic and throws an error. The error
that is thrown relates to the fact that Format-List changes the data so drastically that it is
no longer valid input for a command like Sort-Object.

Task 2: Filter Data on the Pipeline


You have already seen how Select-Object can control some of the data that gets passed along
the pipeline, and that data can be changed drastically when using the Format Cmdlets. If you
want to change which results are passed along instead of the data that passes along with them,
you can use the Where-Object Cmdlet.
1. In addition to the objects being passed into Where-Object, it only takes one additional
parameter: FilterScript. The parameter name is optional here so all you have to do is
provide the script block that is used for the filter.
Get-Process | Where-Object { $_.WS -gt 15MB }

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 85 of 361

Here you are instructing Where-Object to only return objects of which the working set is
greater than 50 megabytes. Where-Object goes through each item in the pipeline,
changing the pipeline variable each time, and executes the filter script to check if the
filter is true or false. If the filter script is true for that item in the pipeline, it is then passed
on to the next command.
2. Where-Object also has a few built-in aliases, one of which can sometimes confuse
people who are new to PowerShell.
Get-Process | Where { $_.Name -eq notepad }
Get-Process | ? { $_.Threads.Count -gt 25 }

The second example, using a question mark, can look confusing. However, it is a simple
alias used for Where-Object and is the number 2 spot atop the list when you execute the
Get-Alias Cmdlet with no parameters in a standard PowerShell instance.
3. Going back to the Select-Object Cmdlet, there is one additional parameter it provides,
which helps to filter data along the pipeline.
Get-Process | Select Name -Unique

Every version of Windows in the recent past will run a number of services that hosted
within the same executable running as separate instances. You could have multiple
PowerShell, ISE, or notepad instances running, among others. The Unique parameter
allows you to filter out duplicate objects and only return those that are distinct.

Task 3: Sorting and Grouping Objects on the Pipeline


You have already seen a few examples using Sort-Object, showing that it synchronously
processes data along the pipeline.
1. Sort running processes by the size of the working set with the following command:
Get-Process | Sort-Object -Property WS

Note: The property parameter name is optional and Sort-Object has a built-in alias
called Sort.

2. When sorting objects, take note of where in the pipeline these objects are.
Get-Process | Sort WS | Select -First 10
Get-Process | Select -First 10 | Sort WS

These two commands have very different meanings. In the first command you are getting
the 10 processes with the smallest working set because you:

Sorted first along the pipeline

Then limited the selection to the first 10

The second command, since you selected the first 10 process objects, will sort only those
first ten objects. It will therefore (very likely) not be the same list of 10 processes.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 86 of 361

3. Sort-Object also allows you to change the order of the sort by using the Descending
parameter, which can be shortened to Desc.
Get-Process | Sort WS Desc | Select -First 10

In the example above, you are getting the 10 largest processes by working set rather than
the smallest 10 as in the previous example.
4. When working with text data, you can also tell Sort-Object to sort case-sensitively.
"abC", "ABc", "deF", "aBc", "DEF", "def" | Sort-object CaseSensitive

This command changes the sort, since lower-case letters are considered to be of lower
value than upper-case letters, just as when you examined the comparison operators.
5. Sort-Object also allows you to only sort unique objects.
"abC", "ABc", "deF", "aBc", "DEF", "def" | Sort-object -Unique

In this case, because you are no longer doing a case sensitive sort, the Cmdlet sees that
there are a number of duplicates. Thus, the result set is limited to a sorted aBc and
def. These are chosen from the list because they are the individual unique items found
last in the pipeline.
6. If you want to get unique objects, it may be more useful to use the Group-Object Cmdlet.
This will allow you to maintain all of the items that are found to be duplicates.
"abC", "ABc", "deF", "aBc", "DEF", "def" | Group-Object

The data returned with Group-Object will, by default, group the data into GroupInfo
objects that contain each individual item for each group. The name of each group will be
the first unique value found for each one: in this case, abC and deF, unlike SortObject -Unique.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 87 of 361

Exercise 4: Pipeline Input and Output


Objectives
In this exercise, you will:

Input and output simple data to and from the pipeline

Work with CSV files

Understand the ConvertTo-* Cmdlets

Scenario
Since the pipeline only goes from left to right, you should be able to provide some kind of
input to the pipeline that cannot be generated from an initial cmdlet or function. To do this,
PowerShell provides a number of simple commands to input and output data to and from the
pipeline.

Log on to VM Environment
Log on to the Windows 7 Enterprise client

Task 1: Understand Basic Input and Output on the Pipeline


Since you are going to be working with data in the pipeline, you first need to create a file to
work with. To do this you can use the Set-Content and Add-Content Cmdlets.
1. Write data to a file using Set-Content.
Set-Content -Path c:\pshell\part1\lesson3\services.txt -Value winrm

This command writes winrm to a file called services.txt. Open the file with notepad to
verify the data was written, then close notepad. Set-Content can also be called by its
built-in alias sc.
2. Append data to the file using Add-Content.
Add-Content -Path c:\pshell\part1\lesson3\services.txt -Value wuauserv
Add-Content c:\pshell\part1\lesson3\services.txt netlogon

Here you are using Add-Content to append data to an existing file. If the file did not
exist, a new one would have been created. Re-open the file in notepad to verify that you
have five service names listed (each on a separate line), then close notepad.
3. You can also pipe data to Set-Content and Add-Content.
winlogon, dnscache | ac c:\pshell\part1\lesson3\services.txt

This command takes the pipeline data of a text array and sends it in by value to the AddContent Cmdlet, appending each pipeline object as a new line within the services.txt file.
Additionally, you are calling Add-Content by its built-in alias.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 88 of 361

4. Set-Content and Add-Content were designed to work with string data. So, if you pass
non-string data to them, PowerShell will convert the objects to strings before writing to
the file.
Get-Process | Set-Content c:\pshell\part1\lesson3\processes.txt

If you open this processes.txt file in notepad, you will see that there is a line item for each
process running on your machine. Unfortunately, the actual information contained on
each line is the string conversion output from a Process object. You can see this by
calling the ToString() method of any process object.
Get-Process | ForEach-Object { $_.ToString() }

5. Set-Content and Add-Content stop the pipeline of data, unless you explicitly tell them
to continue it with the -Passthru parameter. When you use Passthru, you can actually
see the data that gets written to the file.
Get-Process | Set-Content c:\pshell\part1\lesson3\processes.txt -Passthru

In previous steps, you output data to the text file, but were unable to see what was written
there and had to either open the file or look at the value of the ToString() method for
each process. The -Passthru parameter allows this data to be passed along the pipeline so
you can actually see that data, or perhaps take further action upon the objects that were
passed into it.
6. Now that you have created a few files, you can also try to read from them with another
Cmdlet, Get-Content.
Get-Content c:\pshell\part1\lesson3\services.txt

You can see that the data from the file is output to the screen. Each line from the file is
returned as a separate object on the pipeline and each one is a string.
7. Since the Get-Service Cmdlet allows pipeline input for the Name parameter, you can
then take this data and pipe it to Get-Service.
Get-Content c:\pshell\part1\lesson3\services.txt | Get-Service

This command then returns the designated services specified in the file.

Task 2: Work with CSV Files


In other scripting environments, reading in CSV files is a lot of work. Typically, a program
that accepts any kind of file input would need its own implementation to work with CSV files.
Fortunately, PowerShell includes two Cmdlets, Import-CSV and Export-CSV, which
handle this for you.
1. Create a file to work with using the Set-Content and Add-Content Cmdlets.
SC
AC
AC
AC
AC

c:\pshell\part1\lesson3\people.csv
c:\pshell\part1\lesson3\people.csv
c:\pshell\part1\lesson3\people.csv
c:\pshell\part1\lesson3\people.csv
c:\pshell\part1\lesson3\people.csv

Microsoft | Services

GivenName,Surname,Profession
Belinda,Newman,Scientist
Guy,Gilbert,Philanthropist
Holly,Holt,Philosopher
Fabien,Hernoux,Musician

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 89 of 361

AC c:\pshell\part1\lesson3\people.csv Thomas,Andersen,Revolutionary

Open the file in notepad to confirm there are six lines of text starting with the header and
five individuals. Close the file when finished.
2. Now that you have a CSV file to work with, reading it in with PowerShell is quite simple.
Import-CSV c:\pshell\part1\lesson3\people.csv

When you execute this command, it turns the data from the file into objects that get
passed along the pipeline. Each object has properties that correlate with the column
headers from the CSV file. You can also change the delimiter for each value or set the
header information manually if you prefer using the appropriate parameters.
3. You can work with the imported data like any other pipeline data.
ipcsv c:\pshell\part1\lesson3\people.csv | Sort Surname | Select GivenName

Here you are calling Import-CSV using its built-in alias. Then, you are piping the data
out to Sort-Object and Select-Object.
4. Exporting data to a CSV is even easier and provides considerably more information than
when using Set-Content and Add-Content.
Get-Process | Export-CSV c:\pshell\part1\lesson3\processinfo.csv

Here you piped some data to the Export-CSV Cmdlet and PowerShell wrote all the
properties to the file for each individual object, setting appropriate headers in the file.
5. Just like Import-CSV you can also change the headers, delimiter and some other
information. It is important to note that, Export-CSV will overwrite any file that already
exists and there is no built-in functionality for appending to a CSV.
Get-Process | Select First 10 | epcsv c:\pshell\part1\lesson3\processinfo.csv

Here you are limiting process selection to the first 10 objects and then sending them to
Export-CSV using its built-in alias. When you open the processinfo.csv file now, you
will see that it completely overwrote the old data from the previous example.
6. If you wanted display this data on the screen instead of writing it to a file, you can use the
ConvertTo-CSV Cmdlet.
Get-Process | Select id, name First 10 | ConvertTo-CSV

This displays that data as text to the screen because it was passed along the pipeline
rather than out to a file. You can then take that output and send it to another Cmdlet, such
as Send-MailMessage to email it to yourself for later use.
7. The ConvertTo-HTML Cmdlet can be even more useful by taking data and turning it
into an HTML table. It works similar to the ConvertTo-CSV Cmdlet, but gives you more
functionality and converts to HTML.
Get-Process | ConvertTo-HTML > c:\pshell\part1\lesson3\processinfo.html

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 90 of 361

If you open this file with Internet Explorer, you will see a basic HTML table has been
created. If you are familiar with HTML, you can look at the source and you will see it has
properly formatted everything in a standard TABLE element. There are additional
parameters available to alter the output by specifying a CSS file to use for styling or to
add data to the Head, Title, Body, and other areas of the document.
Note: There are a few additional ConvertTo-* Cmdlets included with PowerShell, for
more information use Get-Help ConvertTo-*

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 91 of 361

Lesson 3 Hands-On : Pipeline


Objectives
After completing this lab you will be able to:

Understand PowerShell Operators

Understand the PowerShell Pipeline

Filter and sort with the Pipeline

Prerequisites
The lab requires a Windows 7 client running in a domain environment.

Estimated Time to Complete this Lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 92 of 361

Exercise 1: PowerShell Operators


Objectives
In this exercise, you will:

Use the PowerShell operators to test for conditions.

Use the Where-Object Cmdlet to filter results.

Estimated Time to Complete this Lab


10 minutes

Scenario
Now that you know how WMI can be accessed in Windows, you can use PowerShell 1.0 or
2.0 to get information from it. This exercise concentrates on getting only local information.

Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Open Windows PowerShell Session


On the windows task bar locate the

icon. Click on this icon.

The PowerShell window will open.

Task 1: Using Operators on the Pipeline


Using the PowerShell pipeline operators you can search for an object with specific values.
For the first example, you will look at what services are running on your workstation
1. From PowerShell console, run the following command
Get-service | where-object {$_.status eq Running}

You will see the services that are currently running on your workstation. This is because
the list of services was passed from the Get-Service Cmdlet to the Where-Object
Cmdlet. Using the equals operator, the Where-Object Cmdlet only displays services
whose status is equal to running. You can reverse the logic by using the not equals to
operator
2. From PowerShell console, run the following command
Get-service | where-object {$_.status ne Running}

You will now see the services that are not running.
You can also use the operators to look at other objects. Now, look for PowerShell script
files in the c:\pshell directory.
3. In the PowerShell console, type the following command to search for files:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 93 of 361

Get-childitem c:\pshell recurse | where-object {$_.name like *.ps1}

You will now see any *.ps1 files in the c:\pshell tree.
You can also look for files with other properties. Look for files that are greater than a
particular size.
4. Type the following into the PowerShell console to list all the files from the root of c:
Get-childitem c:\

You will now see all the files that are in c:\. Next lets look for any files that are greater
than 1KB
5. Type the following command in the PowerShell console to find files greater than 1Byte
Get-childitem c:\ | where-object {$_.length gt 1}

You will now see the list of files greater than 1 byte.
6. Type the following command in the PowerShell console to find files greater than 1KB
Get-childitem c:\ | where-object {$_.length gt 1kb}

You will now see the list of files greater than 1KB. Note that this works as KB is a byte
constant in PowerShell. This means that 1KB = 1024 bytes to make it easier to reference
byte values in PowerShell. To extend this further, you will now use 1MB also.
7. Type the following in the PowerShell console to find files greater than 1MB
Get-childitem c:\ | where-object {$_.length gt 1mb}

You will now see any files that are greater than 1MB.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 94 of 361

Exercise 2: The PowerShell Pipeline


Objectives
In this exercise, you will:

Use the PowerShell operators to test for conditions.

Use the where-object Cmdlet to filter results.

Estimated Time to Complete this Lab


10 minutes

Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Open Windows PowerShell Session


On the windows task bar locate the

icon. Click on this icon.

The PowerShell window will open.

Task 1: Using the Pipeline Variable


Using the PowerShell pipeline, you can easily get information from one Cmdlet or object and
pass it to another. Using the pipeline and the pipeline variable, this can even be used to
perform actions.
1. From the PowerShell console, run the following command to read a list of computers into
a variable:
$computers = get-content c:\pshell\part1\lesson3\labs\Computers.txt

This will assign the contents of the computers.txt file to the variable.
2. Type the following command in the PowerShell console to display the list of computers.
$computers

You will now see the list of computers.


Now you will use the pipeline to process this list of computers and ping each computer to
test for connectivity. To do this, you will use the foreach-object Cmdlet
3. Type the following to ping each computer from the variable.
$computers | foreach-object {ping $_}

You will now see the results of the ping command.


Note: Each computers name is passed to the foreach-object one at a time using the
$_ variable. The ping command uses this name to perform the ping.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 95 of 361

This can also be used with other objects, such as files on your computer.
From the PowerShell console, run the following command:
Get-childitem c:\pshell

You will now see the files and folders in c:\pshell.


4. Type the following command to display the full name of each file or folder in the
directory.
Get-childitem C:\pshell | foreach-object {$_.fullname}

The full name for each file or folder will be displayed.


Taking this a step further, you may want to filter to just directories or folders. You can do
this with the property $_.psiscontainer and the Where-Object Cmdlet. The
psiscontainer property is a Boolean property that is true if the object is a directory or
folder.
5. Type the following command to display the full name for each folder in the directory.
Get-childitem C:\pshell | where-object {$_.psiscontainer} | foreach-object
{$_.fullname}

You will now see the full name displayed for any folders in c:\pshell.
Expanding on this, you may want to know how many files or folders are under each subdirectory and the total size of each of these folders.
First, try the command on the c:\pshell folder.
6. From PowerShell console, run the following command to display the count and total size
of the files in c:\pshell. To reduce the size of the command, use aliases.
Gci c:\pshell recurse | measure-object length sum

You will now see displayed the count of files and the sum of the files for the c:\pshell
directory.
Using the foreach-object Cmdlet and the pipeline do the same for each top level
directory in the c:\pshell path. To do this you will combine the commands used in
previous steps.
Get-childitem C:\pshell | where {$_.psiscontainer} | foreach-object {$_.fullname ;
gci $_.fullname recurse | measure-object length -sum}

You will now see displayed the file count and total size of the files for each sub directory
The next example uses services.
7. From the PowerShell console, run the following command to display running services:
Get-service | where-object {$_.status eq Running}

The running services will now be displayed.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 96 of 361

This can also be done with the foreach-object Cmdlet although this does require more
code. This is also using an if statement. This will be covered in more detail in the
scripting lesson.
8. From the PowerShell console , run the following command to display running services:
Get-service | foreach-object {if ($_.status eq Running) {write-host $($_.name)
: $($_.status)}}

Running services will now be displayed. As you are using the write-host Cmdlet you can
also add color to the display.
9. From the PowerShell console , run the following command to display running services
with color:
Get-service | foreach-object {if ($_.status eq Running) {write-host $($_.name)
: $($_.status) foregroundcolor green}}

You will now see the running services displayed in green. Expanding on this you can also
display services not running as red by modifying the if statement.
10. From the PowerShell console, run the following command to display running services
with color:
Get-service | foreach-object {if ($_.status eq Running) {write-host $($_.name)
: $($_.status) foregroundcolor green} else { write-host $($_.name) :
$($_.status) foregroundcolor red}}

You will now see displayed the services and their status in:

Green for running

Red for services that are not running

You might notice that the names of the services are the short names. If you modify the
command above to use $_.displayname instead of $_.name you will see the friendly
name of the service displayed.
11. From the PowerShell console, run the following command to display running services
with color using their displayname:
Get-service | foreach-object {if ($_.status eq Running) {write-host
$($_.displayname) : $($_.status) foregroundcolor green} else { write-host
$($_.displayname) : $($_.status) foregroundcolor red}}

You will notice that the display is not sorted and that the data is displayed as a table
starting with status, name and displayname. You can change this by using the sort-object
Cmdlet.
12. Type the following to sort the services by their status.
Get-service | sort-object status | foreach-object {if ($_.status eq Running)
{write-host $($_.displayname) : $($_.status) foregroundcolor green} else {
write-host $($_.displayname) : $($_.status) foregroundcolor red}}

You will now see the services displayed sorted by their status with color.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 97 of 361

Note: The use of the foreach-object here is to showcase the use of the pipeline and
the processing of each item passed through the pipeline. There are much better ways
of performing the above activities.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 98 of 361

Exercise 3: Filter and Sort with the Pipeline


Objectives
In this exercise, you will:

Use the PowerShell operators to test for conditions

Use the Where-Object Cmdlet to filter results

Estimated Time to Complete this Lab


10 minutes

Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Open Windows PowerShell Session


On the windows task bar locate the

icon. Click on this icon.

The PowerShell window will open.

Task 1: Filtering and Sorting


When using PowerShell commands to collect information, it is useful to be able to:

Filter the information based on values

Sort the information returned

The commands shown below allow you to use these features.


1. From the PowerShell console, run the following command to display running processes:
Get-process

The list of running processes will now be displayed. Now, filter the display to look for
specific processes.
2. From the PowerShell console, run the following command to display running processes
starting with s:
Get-process | where-object {$_.name like s*}

The list of running processes starting with s will now be displayed.


The next property deals with filtering processes based on CPU time used.
3. From the PowerShell console, run the following command to display running processes
with more than one second CPU time consumed:
Get-process | where-object {$_.cpu gt 1}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 99 of 361

The list of running processes consuming more than one second CPU time will now be
displayed.
These can also be combined into one command using the or and and operators.
4. Type the following command to filter processes
Get-process | where-object {$_.name like s* or $_.cpu gt 1}

The examples below show sorting with services.


5. From the PowerShell console, run the following command to display running services:
Get-service | where-object {$_.status eq Running}

The running services will now be displayed.


You will notice that the display is not sorted and that the data is displayed as a table
starting with status, name and displayname. You can change this by using the sort-object
Cmdlet and the format-table Cmdlet.
6. From the PowerShell console, run the following command to sort the services by their
status:
Get-service | sort-object status

You will now see that the services are now sorted by their status. However, the output is
still displayed as the default table and the stopped services are displayed first.
Note: By default PowerShell will perform ascending sorts. You can change this by
adding the -descending option to the command

7. From the PowerShell console, run the following command to sort the services by status in
descending order:
Get-service | sort-object status -descending

Now you will see the running services first and then the stopped services. The following
examples deal with changing the output displayed.
8. From the PowerShell console, run the following command to sort services and change the
display:
Get-service | sort-object status descending | format-table name, displayname,
status

You will now see the services and their status in a table with the service name,
displayname and the status. You will notice that there are some truncated names and
some is space lost. This is because the format-table Cmdlet uses a default column size
without looking at the data returned. You can change this by using the -autosize
parameter.
9. In the PowerShell console, type the following command to sort the services and see the
result of the -autosize option:
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 100 of 361

Get-service | sort-object status descending | format-table displayname, status


autosize

You will now see that the display is much better as it does not truncate the names and
does not waste any white space.
However, you will notice that the services are now sorted by their status and not by their
name or displayname. This can be addressed by adding name to the sort-object Cmdlet
10. In the PowerShell console, type the following command to sort services and see the result
of the -autosize option:
Get-service | sort-object status, name descending | format-table
status autosize

displayname,

You will now see the services sorted by their status and name. However, note that
because you used the -descending parameter the sort is descending. If you remove this
parameter, the sort will be ascending.
11. In the PowerShell console, type the following command to sort services and see the result
of the -autosize option:
Get-service | sort-object status, name | format-table
autosize

displayname, status

You will now see the services displayed and sorted by their name. However, the status is
reversed as S comes before R in the alphabet.
If you use the sort-object Cmdlet normally, you have to choose if the whole sort will be
ascending or descending. However, this is a way of having one property sorted in
ascending order and the other in descending order. This is done via an expression hash
table.
12. In the PowerShell console, type the following command to sort services using the
expression hash table:
get-service | sort-object -property @{Expression="Status";Descending=$true},
@{Expression="Name";Descending=$false} | format-table displayname, status
autosize

Now you will see the services displayed and sorted with the names in ascending order
and the status in descending order.
You may want services to use the displayname instead of the short name. You can do this
by modifying the command.
13. Type the following to sort services using the expression hash table.
get-service | sort-object -property @{Expression="Status";Descending=$true},
@{Expression="DisplayName";Descending=$false} | format-table displayname, status
autosize

You will now see the services displayed and sorted by displayname and then status.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 101 of 361

Finally, you might want to save this information to a file. This can be easily done by
using the redirector operator and specifying a filename.
14. Type the following to sort the services using the expression hash table:
get-service | sort-object -property @{Expression="Status";Descending=$true},
@{Expression="DisplayName";Descending=$false} | format-table displayname, status
autosize > servicestatus.txt

15. Type the following to open the text file in notepad:


Notepad servicestatus.txt

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 102 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 4: PowerShell Providers
Student Lab Manual

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Lesson 4 Demonstration : Providers


Introduction
This lesson will introduce you to the concept of the PowerShell provider model and their use.
It will introduce you to what providers are available, what data the providers contain and how
to operate with the providers.

Objectives
After completing this lab, you will be able to:

Understand the concept of PowerShell providers

Use PowerShell providers and drives to access various different information sources

Understand which providers are single level and multiple level

Create items in different providers

Prerequisites
To complete this lab, you need:

A Windows 7 workstation logged onto with administrator credentials

Estimated Time to Complete this Lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 104 of 361

Exercise 1: Provider Introduction


Objectives
In this exercise, you will:

Learn what Windows PowerShell providers are

List available PowerShell providers

List available PowerShell drives

Scenario
The PowerShell provider model is a system built into PowerShell to allow you to access
different data sources like you access data in a file system. This is achieved by a system of
providers and PowerShell drives. There are several providers and drives already built into
PowerShell to allow you to access various different data types. It is possible to add additional
providers to PowerShell

Task 1: Log on to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password P@ssword

Task 2: Open Windows PowerShell and List the Available Providers


In Windows PowerShell, there are PowerShell providers and PowerShell drives. The provider
is a set of .Net codes that has been written to present the data from the source it is working
with, as if it were a file system. You can also explain drive here, a drive is the way a provider
presents its data, as name implies the idea is to simulate the desk drive convention? While
there are a number of built-in providers installed with PowerShell, it is also possible to add
additional providers to access different data.
The built-in providers are:

Alias provider

Certificate provider

Environment provider

File system provider

Function provider

Registry provider

Variable provider

WS-Management provider

You can get a list of these providers by running the Cmdlet get-psprovider.
1. In the PowerShell console, type the following command to list the available providers.
Get-psprovider
PS C:\Users\administrator> Get-PSProvider

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 105 of 361

Name
---WSMan
Alias
Environment
FileSystem
Function
Registry
Variable
Certificate

Capabilities
-----------Credentials
ShouldProcess
ShouldProcess
Filter, ShouldProcess
ShouldProcess
ShouldProcess, Transactions
ShouldProcess
ShouldProcess

Drives
-----{WSMan}
{Alias}
{Env}
{C, D, E, F...}
{Function}
{HKLM, HKCU}
{Variable}
{cert}

You will see that now you have displayed the names of the providers available, their
capabilities, and the drives associated with them.
While it is useful to see the PowerShell providers listed, this may not be how you would
think of them in terms of accessing information from them. You are more likely to use
them, or think of them as drives.

Task 3: List PowerShell Drives


You can list PowerShell drives using the get-psdrive Cmdlet.
1. In the PowerShell console, type the following command to list the available drives:
get-psdrive
PS C:\Users\administator> Get-PSDrive
Name
---Alias
C
cert
D
Env
Function
HKCU
HKLM
Variable
WSMan

Used (GB)
--------12.83

Free (GB) Provider


--------- -------Alias
19.07 FileSystem
Certificate
FileSystem
Environment
Function
Registry
Registry
Variable
WSMan

Root
---C:\
\
D:\

HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE

Now, you will see the list of PowerShell drives that are available.
You will see the name of the drive that you will use to set the location, the provider that
is presenting the drive, and file system details such as used and free space for the file
system drives.

Task 4: Navigate Through Providers


This section describes how to navigate through various providers and drives. This is simple,
as they are presented as a file system. By changing to the drive for that provider, you can
view the data from it. To do this, the set-location Cmdlet is used with its drive name
specified, followed by a colon. For example, set-location env: would change the location to
the environment drive.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 106 of 361

1. In the PowerShell console, type the following command to set the current location to the
alias drive:
set-location Alias:\
PS Alias:\>

The prompt will now change to PS Alias:\>.


From here, you can list the available alias using the get-childitem Cmdlet, or the dir
alias.
2. In the PowerShell console, type the following command to list the available aliases:
Get-childitem

The list of the current defined alias will now be displayed.


To set the location back to the file system, or to another location, use the set-location
Cmdlet.
If you want to change the location to a particular folder in a drive, you can use the setlocation Cmdlet. In this case, you will change the location to the software folder in the
registry drive HKLM:.
To do this, you need to specify the drive and the path as you would with file system
drives and folders.
3. In the PowerShell console, type the following command to set the location to
HKLM:\software:
Set-location HKLM:\software
PS HKLM:\software>

The prompt will now change to PS HKLM:\software>


From here, if you type get-childitem, you will see the sub-directories from this key.
4. In the PowerShell console, type the following command to list the content of the registry
location:
Get-childitem

To go back to a directory or move up that branch in the tree, use ...


5. In the PowerShell console, type the following command to set the location up one level in
the directory tree:
Set-location ..
PS HKLM:\>

The prompt will now change to PS HKLM:\>.


This indicates that you are now in the root of the drive.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 107 of 361

6. In the PowerShell console, type the following command to set the location back to your
home location:
Set-location $home
PS C:\Users\administrator>

You will see that you can use variables for path locations and that the current location
will have changed to the location you want.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 108 of 361

Exercise 2: Provider Related Cmdlets and Operations


Objectives
In this exercise, you will:

List the various groups of provider cmdlets


Work with the provider and drive Cmdlets
Work with the path related Cmdlets
Work with the item and property cmdlets

Scenario
When using any of the PowerShell providers, there are many Cmdlets that are related to
working with information accessible via the providers. Many of these Cmdlets work in the
same or a similar way for each provider. To identify the Cmdlets related to the providers,
break them down into three groups.

First Group: Cmdlets that work with the providers and drives

Second Group: Cmdlets for navigation and path related operations

Third group: Cmdlets for working with the items, properties and contents of the
information accessible via providers

Task 1: First Group: Provider and Drive Cmdlets


The Cmdlets included in this group are:

Get-psprovider

Get-psdrive

New-psdrive

Remove-psdrive

You are familiar with using get-psprovider and get-psdrive, and therefore use the newpsdrive and remove-psdrive Cmdlets.
The new-psdrive Cmdlet is used to create a new instance of a drive in PowerShell and map it
to an available provider and path.
1. Click Start > Run, type powershell and press Enter.
2. In the PowerShell console, type the following command to list the PSdrives:
Get-psdrive

A list of available PowerShell drives appears.


Notice that for the registry provider there is only the Hkey _Current_User and
Hkey_Local_Machine registry hives available. You do not have access to the
Hkey_Classes_Root, Hkey_Users or Hkey_Current_Config hives.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 109 of 361

This can be fixed by creating a new PowerShell drive and setting its path to the required
hive. You need to provide the drive name, specify the provider that the information is
coming from, and the root path to which you want to map.
3. In the PowerShell console, type the following command to create a new PowerShell
drive:
new-psdrive name HKCR psprovider registry root HKEY_CLASSES_ROOT

A drive called HKCR is created and it will contain the information from the hkey classes
root registry hive.
4. In the PowerShell console, type the following command to list the PSdrives:
Get-psdrive

The HKCR drive is listed and available.


You can also create a new drive to map directly to an existing path in another drive.
5. In the PowerShell console, type the following command to create a file system provider,
PowerShell drive:
new-psdrive name mydocs psprovider filesystem root
c:\users\administrator\documents

6. In the PowerShell console, type the following command to set the location to the new
drive:
set-location mydocs:

You will see that the prompt has changed to PS mydocs:\> indicating that you are in the
mydocs drive.
7. In the PowerShell console, type the following command to list the contents of the drive:
Get-childitem

The list of files and folder available from the mydocs drive appears.
Along with creating new drives, you can also remove drives. Note that this should only
be used on additional drives you have created and not on inbuilt drives.
8. In the PowerShell console, type the following command to set the location back to C:.
Set-location c:

9. In the PowerShell console, type the following command to remove the mydocs drive:
Remove-psdrive name mydocs

This will remove the mydocs drive from the current shell. You can confirm this with getpsdrive.
10. In the PowerShell console, type the following command to list the available PowerShell
drives.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 110 of 361

Get-psdrive

You will notice that the current drive is removed.

Task 2: Second Group: Navigation and Path Related Operation Cmdlets


You are now familiar with the set-location Cmdlet. Let us now focus on the other Cmdlet
that you may not be familiar.
The list of navigation and path Cmdlets are:

Get-location

Pop-location

Push-location

Set-location

Join-path

Convert-path

Split-path

Resolve-path

Test-path

Let us start by understanding the test-path Cmdlet. This is very useful as it allows you to test
if an object exists or not. This works with all providers and hence, along with testing if files
and folders exist, you can test for registry keys, certificates, or even variables. To use it all,
you need type test-path followed by the path of the object of interest.

Task 3: Test Path


1. In the PowerShell console, type the following command to test the C:\temp directory:
Test-path c:\temp

The result, indicating that C:\ path is valid appears. If you test for a location that does not
exist or file that does not exist the result will be false.
2. In the PowerShell console, type the following command to test the path C:\fakefolder:
Test-path c:\fakefolder

The result, indicating false appears. Let us test for a file.


3. In the PowerShell console, type the following command to test for the file
C:\notafile.txt:
Test-path c:\notafile.txt

Again, a false is returned as this file does not exist. Let us try a file that does exist.
4. In the PowerShell console, type the following command to test the file
C:\fso\servers.txt:
Test-path c:\fso\servers.txt

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 111 of 361

This returns a true as the files exists.


You can also use test path on UNC paths (those that can be used as a verificationexception handing mechanism while writing script that sets or gets data to UNC paths).
5. In the PowerShell console, type the following command to test the path
\\syddc01\netlogon:
Test-path \\syddc01\netlogon

Note: The current location must be a file system provider location or the UNC will
return false regardless if it exists or not. This is also true when using set-location on
UNC paths. You must first be in a file system provider location.

Let us now look at something other than the file system. You can test to see if an
environment variable exists.
6. In the PowerShell console, type the following command to test the systemroot
environment variable:
Test-path env:\systemroot

You will see that the result is true.


As you can see, test-path works with all providers in the same way.

Task 4: Get Location


Get-location can be used to determine the current location. This also returns additional
information that can be useful when dealing with psdrives and providers.
1. In the PowerShell console, type the following command to determine the current
location:
Get-location

The current path appears with additional information.


2. In the PowerShell console, type the following command to see more information about
the location:
Get-location | format-list *

The drive, provider, providerpath and path appears.


You can extract only the path, which can then be assigned to a variable.
3. In the PowerShell console, type the following command to set $mypath to the current
path:
$mypath = (get-location).path

4. In the PowerShell console, type the following command to view the value of $mypath:
$mypath

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 112 of 361

The variable $mypath contains only the path value.

Task 5: Push Location and Pop Location


These Cmdlets work in combination. The push-location Cmdlet adds the current path to the
stack, and pop-location changes to the last location added to the stack.
The best way to understand this is to use them.
1. In the PowerShell console, type the following command to set the current location to the
you home location:
Set-location $home

2. In the PowerShell console, type the following command to add the location to the stack:
Push-location

3. In the PowerShell console, type the following command to set the location to env: drive:
Set-location env:

4. In the PowerShell console, type the following command to add the location to the stack:
Push-location

5. In the PowerShell console, type the following command to set the location to the hklm:
drive:
Set-location hklm:

The current path is set to PS HKLM:\>.


6. In the PowerShell console, type the following command to change to the first location
from the stack:
Pop-location

The current location changes to the last location from where you ran push-location, PS
Env:\>.
7. In the PowerShell console, type the following command to change to the next location
from the stack:
Pop-location

The prompt changes to the first location from which you ran push-location.

Task 6: Resolve Path


Another useful Cmdlet is the resolve-path Cmdlet. This is used to resolve paths of objects
using wildcards.
1. In the PowerShell console, type the following command to set the location to c:\.
Set-location c:\

2. In the PowerShell console, type the following command to resolve the path *program*:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 113 of 361

Resolve-path *program*
PS C:\> resolve-path *program*
Path
---C:\Program Files

The path, *program* will be resolved to C:\program files.


You can also use the convert-path Cmdlet to convert a PowerShell path to a PowerShell
provider path that can be used with the ps-drive Cmdlet
3. In the PowerShell console, type the following command to convert the path
HKLM:\software\microsoft:
Convert-path path HKLM:\software\microsoft
HKEY_LOCAL_MACHINE\software\microsoft

The path is converted to HKEY_LOCAL_MACHINE\software\microsoft. This can be


used as the root path when using the new-psdrive Cmdlet.

Task 7: Split Path


Another useful Cmdlet when dealing with providers is the split-path Cmdlet.
This can be used to easily grab the filename, or parent path for an object. The Cmdlet accepts
input from the pipeline.
1. In the PowerShell console, type the following command to get only the filename:
get-item c:\windows\windowsupdate.log | split-path leaf

Only the name of the file, windowsupdate.log appears.


You can also get only the parent path.
2. In the PowerShell console, type the following command to get the parent path of the file:
get-item c:\windows\windowsupdate.log | split-path parent

Task 8: Join Path


This Cmdlet is used to join a parent path and a child path. This also works with wildcards.
1. In the PowerShell console, type the following command to join the path together using
wildcards:
join-path path program* -childpath *microsoft* -resolve

The path is resolved to a number of directories for Microsoft products.

Task 9: Group Three: Item and Property Related Cmdlets


When working with the PowerShell providers, the items contained within these providers is
of most interest. To work with items in providers, there is a large set of item, item property,
and content Cmdlets that are available for these operations. Interestingly, these commands

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 114 of 361

work in a similar way for all the providers. This allows a standard syntax to be used
irrespective of the individual provider or item in use.
The Cmdlets that work with items, item properties and content are:

Clear-item

Copy-item

Get-item

Invoke-item

Move-item

New-item

Remove-item

Rename-item

Set-item

Clear-itemproperty

Copy-itemproperty

Get-itemproperty

Invoke-itemproperty

Move-itemproperty

New-itemproperty

Remove-itemproperty

Rename-itemproperty

Set-itemproperty

Add-content

Clear-content

Get-content

Set-content

The best way to explore using these is to use them in the context of providers. You will try
this in the next exercise.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 115 of 361

Exercise 3: Single Level Providers


Objectives
In this exercise, you will:

Work with the alias provider


Work with the environment provider
Work with the function provider
Work with the variable provider

Scenario
When working with PowerShell providers they can be split into two major groups:

Single level providers

Multiple level providers

This exercise will focus on single level providers. Single level providers are providers that
use the file system model and do not have sub folders. That is, all items of interest are
effectively located in the root of the drive.
The single level providers available are:

Alias provider

Environment provider

Function provider

Variable provider

Task 1: Alias Provider


Let us look at the alias provider first. This provider allows access to current defined aliases. It
is assessable via the alias: drive.
1. Open the PowerShell console.
2. In the PowerShell console, type the following command to set the location to the alias:
Set-location alias:\

3. In the PowerShell console, type the following command to list the aliases:
Get-childitem

The list of currently defined aliases appears.


Notice that there are no sub folders. This is because, it is a single level provider and all
items are in the root of the drive.
4. In the PowerShell console, type the following command to get the dir alias:
Get-item dir

The dir alias appears.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 116 of 361

You can also create a new alias using the new-item Cmdlet.
5. In the PowerShell console, type the following command to create a new alias:
new-item name myalias value get-help

This will create a new alias, myalias.


6. In the PowerShell console, type the following command to execute the alias:
Myalias

The get-help Cmdlet executes.


You can remove the alias using remote-item.
7. In the PowerShell console, type the following command to remove the alias:
Remove-item myalias

8. Type myalias to view the error.


Myalias

No error appears as the alias has been removed.

Task 2: Environment Provider


Let us now look at environment provider. This is available via the env: drive:
1. In the PowerShell console, type the following command to set the location to env: drive:
cd Env:

2. In the PowerShell console, type the following command to list the environment variables:
Get-childitem

The list of environment variables available appears. You can also get a particular variable
of interest.
3. In the PowerShell console, type the following command to get the systemroot variable:
Get-item systemroot

The systemroot variable will now appear. You can also address using the full path to the
item from any location.
4. In the PowerShell console, type the following command to set the location to C: drive:
Set-location c:

5. In the PowerShell console, type the following command to get the systemroot variable
with full path:
get-item env:\systemroot

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 117 of 361

You can also create new environment variables using the new-item Cmdlet. However,
note that these are not permanent. Variables created here will only be available to the
current PowerShell console session. The variable will be deleted when the current session
expires. If you need to create a new permanent variable, then you will have to create the
variable in the registry, or via the control panel.
There is an alternative way of getting the value of an environment variable. This is by
using $env:<variablename>.
6. In the PowerShell console, type the following command to get the windir value:
$env:windir

Only the value of the variable appears.


Another task that can be very useful is to test if a particular environment variable exists.
This can be achieved using the test-path Cmdlet.
7. In the PowerShell console, type the following command to test the temp variable:
test-path env:\temp

The result is true as this variable is defined.

Task 3: Function Provider


The function provider is something unique to PowerShell. This allows you to list the current
defined functions as an object. It is also possible to create a new function using the provider
and to modify the content of a function. First, let us list the currently defined functions. Each
function will have a name, using which it can be called, and a definition, which is the code
executed for the function.
1. In the PowerShell console, type the following command to set the location to the function
drive:
set-location function:

2. In the PowerShell console, type the following command to list the contents of the drive:
Get-childitem

The list of functions currently defined appears. You will notice the 26 functions, A: to Z:.
These are not aliases. The reason they are not aliases is because, they are not only a
reference to Cmdlet, but are set-location <driveletter>. An alias is only a different name
of a Cmdlet, the only way the A: to Z: commands can work is through a function.
Let us filter out the A: to Z: functions so that you can see the other functions.
3. In the PowerShell console, type the following command to filter the A-Z functions:
get-childitem | where-object {$_.definition notlike set-location*}

A list of normal functions defined appears.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 118 of 361

It is also possible to create a new function here, test if a function is defined with test-path,
rename a function with rename-item, or delete a function with delete-item. The
definition or code to execute a function can also be changed.
Note: Ensure not to use this to change the inbuilt functions as this may cause unknown
issues with PowerShell.

Task 4: Create, Rename and Redefine Functions


1. In the PowerShell console, type the following command to create a function:
new-item name myfunction value write-host This is my function, get your own!

2. In the PowerShell console, type the following command to execute the function:
myfunction

The text, This is my function get your own! Appears.


3. In the PowerShell console, type the following command to rename the function:
rename-item myfunction newname ourfun

4. In the PowerShell console, type the following command to execute the renamed function:
ourfun

The function runs with the new name.


5. In the PowerShell console, type the following command to redefine the function:
set-item ourfun value write-host all your functions are belong to us!

Note that this is not the correct way to create functions. This was only to demonstrate the
function provider. The correct way to define functions will be covered in module 6.

Task 5: Variable Provider


The variable provider is another provider that is unique to Windows PowerShell. This
provider allows you to see currently defined variables and the values of these variables. This
information is available through the variable drive.
1. In the PowerShell console, type the following command to set the location to the variable
drive:
Set-location variable:

2. In the PowerShell console, type the following command to list the contents of the drive:
get-childitem

The currently defined variables and their values appear. Note that the names of the
variables do not include $. The $ sign is used to tell PowerShell that you are working
with a variable. It is not actually part of the variable name.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 119 of 361

As with all providers, you can test if a variable exists, create new variables, or rename
them. These operations can also be performed using the assignment operator.

Task 6: Delete Variables


The ability to delete variables is very useful.
1. In the PowerShell console, type the following command to create a variable:
$deleteme = Temp variable

2. In the PowerShell console, type the following command to get the value of $deleteme:
$deleteme

The contents of the variable appear.


3. In the PowerShell console, type the following command to delete the variable:
Remove-item path variable:\deleteme

The variable is deleted from all locations as you have specified the full path to the object.
Deleting a variable can also be done using remove-variable. Both of these will result in
the variable being destroyed (not set to null or blank). This is important if the information
stored in the variable is critical.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 120 of 361

Exercise 4: Multiple Level Providers


Objectives
In this exercise, you will:

Scenario
In addition to single level providers, PowerShell also has multiple level providers. The major
difference between single level providers and multiple level providers is that the multiple
level providers have containers as well as items contained in them. This presents the
information available via the provider as in a file system. A file system also has items,
containers and sub containers.
The multiple level providers available are:

Filesystem provider

Registry provider

Certificate provider

WSman provider

Task 1: Certificate Provider


Let us look at the certificate provider. This provider allows access to certificate stores on the
machine. It is assessable via the cert: drive.
1. Open the PowerShell console.
2. In the PowerShell console, type the following command to set the location to the cert:
drive:
Set-location cert:

3. In the PowerShell console, type the following command to list the contents:
Get-childitem

Two containers are now available, the CurrentUser and LocalMachine containers.
Let us navigate to the local machine folder.
4. In the PowerShell console, type the following command to set the location to the local
machine container:
Set-location cert:\localmachine

5. In the PowerShell console, type the following command to list the contents:
Get-childitem

The list of certificate stores for the local machine appears. If you change your location to
one of these stores, you can see the certificates in it.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 121 of 361

6. In the PowerShell console, type the following command to set the location to the ca
container:
Set-location ca

7. In the PowerShell console, type the following command to list the contents:
Get-childitem

The list of certificates appears. Note that thumbprint is the name of the certificate used
when using the item Cmdlet. As thumbprints are not very friendly, it is highly
recommended that you enable quick edit mode for PowerShell to allow you to cut and
paste.
Let us now look at one of the certificates in detail.
8. In the PowerShell console, type the following command to get a certificate:
get-item tab

This will now get one certificate. There is more information available for the certificate.
To access this, pipe this to format-list *.
9. In the PowerShell console, type the following command to display the details of the
certificate:
get-item tab | format-list *

The details available for the certificate appears.


Another useful feature when working with the certificate provider is to search for
certificates by their subject name, or part of it.
10. In the PowerShell console, type the following command to set the location to
cert:\localmachine:
set-location cert:\localmachine

11. In the PowerShell console, type the following command to search for certificates that
have Microsoft in the subject:
get-childitem recurse | where {$_.subject like *Microsoft*}

The list of certificates in the localmachine store that contain Microsoft in the subject
name appears.

Task 2: Registry Provider


The registry provider is one of the very useful features of PowerShell. This provider allows
you easy access to the local machine and current user hives. The other hives can also be
accessed by creating additional drives as demonstrated previously. The registry provider is
available via the HKLM: and HKCU: drives.
1. In the PowerShell console, type the following command to change the current location to
the HKLM: drive:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 122 of 361

set-location hklm:\

The current location is now HKLM:\>.


2.

In the PowerShell console, type the following command to list the contents:
Get-childitem

The containers accessible from the root of the HKLM drive appear. Note that the error
you get is expected. This is due to the security key that is accessible only by the system
account.
3. In the PowerShell console, type the following command to change the location of the
autorun programs for the system key:
Set-location .\software\Microsoft\powershell\1\shellids\Microsoft.PowerShell

The current location is now changed to the run key. From here, see the items you have.
4. In the PowerShell console, type the following command to list the contents:
Get-childitem

There is no result. This is due to the slightly different way the registry provider works.
The registry keys are represented as folders, but the registry values that you would expect
to be presented as items are not. They are properties of the key. That is, instead of using
the get-item, or get-childitem Cmdlets, you need to use the get-itemproperty Cmdlet to
read a value.
5. In the PowerShell console, type the following command to go one level up the tree:
Set-location ..

6. In the PowerShell console, type the following command to get the properties of the run
key:
Get-itemproperty path .\Microsoft.Powershell

The registry values appear.


You can isolate this down to just the value.
7. In the PowerShell console, type the following command to extract only the value:
(get-itemproperty path .\Microsoft.Powershell name `
ExecutionPolicy).ExecutionPolicy

Only the value for Execution Policy appears, but this requires you knowing the name of
the value you want.
There is an easier way to do this using a method call on the registry key.
8. In the PowerShell console, type the following command to assign the registry key to a
variable:
$regkey = Get-item Microsoft.PowerShell

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 123 of 361

9. In the PowerShell console, type the following command to get the value using a method
call:
$regkey.getvalue(ExecutionPolicy)

You can also create registry keys using the new-item Cmdlet.
10. In the PowerShell console, type the following command to change the location to the
software key:
Set-location hklm:\software

11. In the PowerShell console, type the following command to create a registry key under the
software key:
New-item mysoftware

This will create the new registry key under the software key.
12. In the PowerShell console, type the following command to display the subkey of the
software key:
Get-childitem

The software key appears. Now, create a registry value. The path needs to be the registry
key under which you will create the value and you need to specify the name and value of
the registry property.
13. In the PowerShell console, type the following command to create a registry value:
New-itemproperty path mysoftware name myregvalue value This is my registry
value

This will create the registry value as a string. You can also create dwords or other data
types by adding the type parameter.
14. In the PowerShell console, type the following command to create a registry dword:
New-itemproperty path mysoftware name mydword value 0x23 type dword

15. In the PowerShell console, type the following command to check our registry values
created:
Get-itemproperty mysoftware

Task 3: WSman Provider


The WSman provider allows access to the Windows Remote Management service
configuration. This simplifies the configuration of the winRM service, and allows this to be
checked. This is available via the WSman drive. As this is a multiple level provider, there are
many settings available.
1. In an elevated PowerShell console, type the following command to change to the
WSman drive:
Set-location wsman:\

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 124 of 361

2. In the PowerShell console, type the following command to display the contents of this
drive:
Get-childitem

The root of the drive contains one container, the localhost container. It is inside this
container that you find the configuration for various WinRM settings and components.
3. In the PowerShell console, type the following command to list the contents of the
container:
Get-childitem localhost | format-table -autosize

Some settings, and additional containers that contain further settings appear.
4. In the PowerShell console, type the following command to change to the client container:
Set-location localhost\client

5. In the PowerShell console, type the following command to display the contents of the
client folder:
Get-childitem

You can modify the values of these settings using the set-item Cmdlet. This will be
covered later in the PowerShell remoting lesson.

Task 4: File System Provider


The final multiple level provider that will be discussed in this module is the file system
provider.
When working with the file system provider in Powershell, you will notice some difference in
the working when compared to what you may be used to. This is due to the object-oriented
nature of PowerShell. The file system provider will make any file system drive available by
its drive letter. If you have multiple drives on your system, PowerShell will present these. If
you only have one drive available, then you will only see one drive.
1. In the PowerShell console, type the following command to list the file system drives
available:
Get-psdrive | where-object {$_.provider like *filesystem*}

The file system drives available appear.


2. In the PowerShell console, type the following command to set the current location to the
root of c drive:
Set-location c:\

3. In the PowerShell console, type the following command to display the contents:
Get-childitem

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 125 of 361

The contents of the C drive appear. This will include both files and folders. You can filter
the view such that you will only see files, or folders. To do this, use a property called,
psiscontainer.
4. In the PowerShell console, type the following command to display only folders:
Get-childitem | where-object {$_.psiscontainer}

Only the folders appear. Note that you can use the psisontainer property without an
operator as it is a Boolean value.
5. In the PowerShell console, type the following command to display only the files:
Get-childitem | where-object {!$_.psiscontainer}

Only the files appear. The ! sign represents a NOT operator and reverses the logic, so
look for objects where psiscontainer is false.
6. In the PowerShell console, type the following command to display the properties
available for files and folders:
Get-childitem | get-member membertype *property*

The properties for both system.io.directory and system.io.fileinfo types appear. These
are .Net framework types that represent the files and folders on the system.
Note the properties with names that start with PS and are of type NoteProperty. These
are additional properties that are added to the display by PowerShell. This is because you
are accessing the items via the provider. These properties have useful information.

The PSChildname property contains the name of the item

The PSDrive property contains the PowerShell drive the item is from

The PSIscontainer property contains the container status of the item

The PSParentPath property contains the PowerShell parent path of the object. This
includes the provider reference

The PSPath property contains the full PowerShell path of the object. This includes
the provider reference

The PSProvider property contains the PowerShell provider that the object is from

These properties are added to any object accessed through a PowerShell provider.
7. In the PowerShell console, type the following command to create a new directory:
New-item name myfolder type directory

This will create a new directory. The type parameter is required. As the file system can
contain both files and directories, you need to define the object you are creating.
8. In the PowerShell console, type the following command to change the current location to
C:\myfolder:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 126 of 361

Set-location c:\myfolder

9. In the PowerShell console, type the following command to create a file:


New-item name machinenames.txt type file

This will create a file. Note that the file length is current 0. This is a completely empty
file. It is also possible to create a file with data in it at the same time.
10. In the PowerShell console, type the following command to create a file with contents:
New-item name machinenames.txt type file value Machinenames

This will create the file and populate it with the data from the value parameter.
11. In the PowerShell console, type the following command to read the data from the file:
Get-content machinenames.txt

The contents of the file appear.


12. In the PowerShell console, type the following command to add contents to the file:
Add-content machinenames.txt value syddc01

13. In the PowerShell console, type the following command to add more data to the file:
Add-content machinenames.txt value w7client

14. In the PowerShell console, type the following command to read the contents of the file
again:
Get-content machinenames.txt
Machinenamessyddc01
w7client

Notice that machinenames and syddc01 are on the same line. This is because, when the
file was created, the value specified was written to the file as it was. This did not include
a new line character. When the add-content commands were used, they added the new
line character. This should be taken care of.
15. In the PowerShell console, type the following commands to set the contents of the file:
Set-content machinenames.txt value Myservers
add-content machinenames.txt value syddc01
add-content machinenames.txt value w7client

16. In the PowerShell console, type the following command to get the file contents:
Get-content machinenames.txt
PS C:\myfolder> Get-Content .\machinenames.txt
Myservers
syddc01
w7client

The set-content Cmdlet will overwrite the file. This Cmdlet also adds a new line after
setting the contents. The add-content Cmdlet also does the same.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 127 of 361

17. In the PowerShell console, type the following command to rename the file:
Rename-item machinenames.txt newname servernames.txt

18. In the PowerShell console, type the following command to list the files:
Get-childitem

The machinenames.txt file no longer exists and is now called servernames.txt.


19. In the PowerShell console, type the following command to delete the file:
Remove-item servernames.txt

This will delete the file. You can also delete directories.
20. In the PowerShell console, type the following command to create a new subdirectory:
New-item name mysub1 type directory

21. In the PowerShell console, type the following command to create a file in the
subdirectory:
New-item path .\mysub1 name deleteme.txt value delete this file type file

22. In the PowerShell console, type the following command to create a second subfolder:
New-item name mysub2 type directory

23. In the PowerShell console, type the following command to list the files and folders
recursively:
Get-childitem recurse
PS C:\myfolder> Get-childitem -recurse
Directory: C:\myfolder
Mode
---d---d----a---a---

LastWriteTime
------------11/09/2011
8:21 PM
11/09/2011
8:24 PM
11/09/2011
7:56 PM
11/09/2011
8:11 PM

Length Name
------ ---mysub1
mysub2
0 myfile.txt
29 servernames.txt

Directory: C:\myfolder\mysub1
Mode
----a---

LastWriteTime
------------11/09/2011
8:21 PM

Length Name
------ ---16 deleteme.txt

You now have an empty subdirectory and one with a file in it.
24. In the PowerShell console, type the following command to delete the mysub2 directory:
Remove-item mysub2

The command runs without a return.


25. In the PowerShell console, type the following command to delete the mysub1 directory:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 128 of 361

Remove-item mysub1

You will be prompted to confirm that you want to delete the directory and all child items,
because the directory contained a file. If you want to perform this action without the
prompt you can specify the recuse option. Use this carefully, as you will not be
prompted to confirm the action.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 129 of 361

Lesson 4 Hands-On : Providers


Introduction
This is the self-paced section for the providers lesson. In this lab, you will use various
providers to perform operations.

Objectives
After completing this lab, you will be able to:

Work with the environment provider to create and test variables

Work with the certificate provider to search for certificates by their properties

Export the details of a certificate as a text file

Work with the registry provider to create registry keys

Work with the registry provider to create registry values

Edit registry values to filter out unwanted values

Prerequisites
To complete this lab, you need:

A Windows 7 workstation logged onto with administrator credentials

Estimated Time to Complete this Lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 130 of 361

Exercise 1: Work with Environment Provider


Objectives
In this lab, you will:

Set location to the environment provider and create new variables

Export variables to a file and import variables

Task 1: Log On to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell


On the Windows taskbar, click

The PowerShell console opens.

Task 3: Set Location to Environment Provider and Create New Variables


1. In the PowerShell console, type the following command to set the location to the
Environment provider drive:
Set-location env:\

Now, create multiple variables. This will only be available for the current session. You
can make a permanent environment variable by editing the registry.
2. In the PowerShell console, type the following command to create an environment
variable:
New-item name AssetTag value 12345ABCD

3. In the Powershell console, type the following command to create another environment
variable:
New-item name SOE_Version value WIN7_X86_CONTOSO_R1.2

4. In the PowerShell console, type the following command to prompt for input:
$Department = read-host Please enter your department

5. Type a department name of your choice.


The $department variable will contain the input you have entered.
6. In the PowerShell console, type the following command to create an environment
variable with the PowerShell variable data:
New-item name department value $department

The $department variable is expanded, and then the value for the department
environment variable is assigned.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 131 of 361

7. In the PowerShell console, type the following command to create a variable from other
variables:
New-item name CurrentUser value $env:userdomain\$env:username

The variables are again expanded and a \ is added between them.


8. In the PowerShell console, type the following command to list the variables created:
Get-childitem

The new variables that you have created are visible.

Task 4: Export Variables to a File


1. In the PowerShell console, type the following command to export the variables to a CSV
file:
Get-childitem | export-csv notypeinformation `
c:\Pshell\part1\lesson4\labs\variables.csv

This will export the current variables to a csv file. This file will contain all the properties
of the items, including their PS properties as well their name and values. The
notypeinformation option is used to prevent PowerShell from including type information
in the file. This information is only useful when you are going to import information from
a csv and keep the type mapping.
2. In the PowerShell console, type the following command to view the csv file in Notepad:
Notepad c:\pshell\part1\lesson4\labs\variables.csv

You will see that there is a lot of information in the file.

Task 5: Open a New PowerShell Console and Import File


This new PowerShell console will not contain the new variables you have previously created.
You can check this by listing the current variables.
1. In the new PowerShell console, type the following command to set the location to the
Environment drive:
Set-location env:\

2. In the new PowerShell console, type the following command to list the variables:
Get-childitem

The variables AssetTag, SOE_Version, department and current user no longer exist.
Now, import the variable details you exported to the csv file.
$myenv = import-csv c:\pshell\part1\lesson4\labs\variables.csv

3. In the new PowerShell console, type the following command to view the imported data:
$myenv

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 132 of 361

The default view is a list and all the properties for each variable appear. You can change
this to display a similar view to the original variables.
4. In the new PowerShell console, type the following command to reformat the date:
$myenv | format-table name, value

The name and value are now displayed in a table format.


5. In the new PowerShell console, type the following command to test the variables
imported:
$myenv | foreach {write-host "Variable: $($_.name) exists $(test-path
env:\$($_.name))"}

A list of the variables and a true or false result if the variable current exists appear. The
command above uses the foreach Cmdlet that passes each item from the variable one at a
time to the script block section. The script block section is the {} part. This is a block of
code that will be run for each item. The script block uses the write-host Cmdlet and the
pipeline variable the $_ to display the name of each variable. It also tests if the variable
exists using the test-path Cmdlet.
Sub expressions can also be used with the $( ). This allows you to extract the value of the
name and value properties. You can create any variables that do not exist.
6. In the new PowerShell console, type the following command to create any variables that
do not exist:
$myenv | foreach {if (!$(test-path env:\$($_.name))) {new-item path
env:\$($_.name) value $($_.value)}}

This command uses the if statement and the result of the test-path Cmdlet to find any
variables that does not exist. If they do not exist, the new-item Cmdlet is executed to
create the variable and the value.
7. In the new PowerShell console, type the following command to list the variables:
Get-childitem

The variables AssetTag, SOE_Version, department and currentuser now exist.


8. In the new PowerShell console, type the following command to test the variables
imported:
$myenv | foreach {write-host "Variable: $($_.name) exists $(test-path
env:\$($_.name))"}

All variables listed exist as true.


9. In the console type the following to return to the c:
Set-location c:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 133 of 361

Exercise 2: Work with the Certificate Provider


Task 1: Log On to VM Environment
Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell


1. On the Windows taskbar, click

The PowerShell console opens.

Task 3: Set Location to Certificate Provider


1. In the PowerShell console, type the following command to set the location to the
Certificate provider drive:
Set-location cert:\

2. In the PowerShell console, type the following command to change to the local machine
certificate container:
Set-location localmachine

The prompt will now be located in the localmachine certificate store. From here, you can
search for certificates given their properties.
First, search for certificates that have expired.
To do this, you need to create a value in datetime format to compare it to the value of the
certificates.
3. In the PowerShell console, type the following command to create a datetime value:
$today = get-date

4. In the PowerShell console, type the following command to search for the certificates that
have expired:
Get-childitem recurse | where-object {$_.notafter lt $today}

The certificates that have an expiry, or notafter property value less than todays date
appear. You can also add them to a variable and filter out any containers that may be
included.
5. In the PowerShell console, type the following command to add the expired certificates to
a variable and filter out any containers:
$expiredcerts = gci -recurse | where {$_.notafter -lt $today -and $_.psiscontainer
-ne $true}

$expiredcerts will now contain the expired certificates. You can examine one of the
certificates using array addressing to look at that certificate.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 134 of 361

6. In the PowerShell console, type the following command to examine one certificate from
the variable:
$expiredcerts[0] | format-list *

The details for the first certificate in the variable appear. You can look at other
certificates using different numbers in between the [ ].
You can also look at valid certificates using a different logic.
7. In the PowerShell console, type the following command to search for current valid
certificates:
$validcerts = gci -recurse | where {$_.notafter -gt $today -and $_.notbefore -lt
$today}

The valid certificates are assigned to the validcerts variables.


It is also possible to check if the certificate is valid with the method call verify.
8. In the PowerShell console, type the following command to display the certificate subject
name:
$validcerts[0].subject

9. In the PowerShell console, type the following command to check if the certificate is
valid:
$validcerts[0].verify()

You will see that the result is true, as this certificate is valid. You can test one of the
expired certificates that is not valid.
10. In the PowerShell console, type the following command to display the certificate subject
name:
$validcerts[0].subject

11. In the PowerShell console, type the following command to check if the certificate is
valid:
$expiredcerts[0].verify()

You will see that the certificate is not valid.


Let us get some more details on the expired certificate
12. In the PowerShell console, type the following command to get the certificate name:
$expiredcerts[0].GetNameInfo(simplename,$true)

13. In the PowerShell console, type the following command to get the type of the certificate:
$expiredcerts[0].getformat()

14. In the PowerShell console, type the following command to certificate issuing authority:
$expiredcerts[0].getissuername()

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 135 of 361

15. In the PowerShell console type the following to return to the c:


set-location c:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 136 of 361

Exercise 3: Working with the Registry provider


Task 1: Log On to VM Environment
Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell


On the Windows taskbar, click

The PowerShell console opens.

Task 3: Set Location to Registry Provider


1. In the PowerShell console, type the following command to set the location to the
environment provider drive:
Set-location hklm:\software

2. Now, type the following command to create a registry key:


New-item name contoso

3. In the PowerShell console, type the following command to assign the registry key to a
variable for later reference:
$mykey = get-item hklm:\software\contoso

4. In the PowerShell console, type the following command to create an array:


$departments = Sales, Marketing, IT_Support, Silly_Walks, Legal,
HR, Administration

5. Type the following command to create a multi string registry value:


New-itemproperty path hklm:\software\contoso name Departments value `
$departments type multistring

6. Type the following command to check the value of the registry key property:
$mykey.getvalue(departments)

The values of the departments registry property appear.


It has been decided that the department of Silly Walks is no longer needed at Contoso. As
such, you need to remove it from the list of departments and keep all other departments.
You can do this with two simple steps using PowerShell.
7. In the PowerShell console, type the following command to create a new list of
departments:
$newdepartments = $mykey.getvalue(departments) | where-object {$_ -notlike
Silly_walks}

This command will assign everything to the variable $newdepartments except the value
you filter with the where-object code, Silly_walks.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 137 of 361

8. In the PowerShell console, type the following command to check the contents of
$newdepartments:
$newdepartments

The names, Sales, Marketing, IT_Support, Legal, HR, Administration appear but not
Silly_walks. Note that all the work is done by the where-object Cmdlet using the
notlike operator.
9. In the PowerShell console, type the following command to set the value of the property to
the new list:
Set-itemproperty path hklm:\software\contoso name departments value `
$newdepartments

Now, verify the value of the department property.


10. In the PowerShell console, type the following command to check the registry property:
$mykey.getvalue(departments)

11. In the PowerShell console type the following to return to the c:


set-location c:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 138 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 5: PowerShell Variables and Type
Fundamentals
Student Lab Manual

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Lesson 5 Demonstration : Variables and Type


Fundamentals
Introduction
In this module, we will learn about the different variables available in Windows PowerShell.
Along with the understanding of the usage of the variables, we will also look at the different
types of variables available in PowerShell. Each of them is used for a specific purpose.
Effective use of variables, arrays, and hash tables is a key for an administrator to prepare
scripts for daily administrative tasks.

Objectives
After completing this lab, you will be able to learn how to:

Create various types of variables and manipulate with the values

Understand Arrays and Hash Tables and how to use them

Understand how variables, arrays, and hash tables could be helpful for building basic
scripts

Prerequisites
To complete this lab, you need:

Windows 2008 and Windows 7 workstation logged onto with administrator credentials

Estimated Time to Complete this Lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 140 of 361

Exercise 1: Working with Variables


Objectives
In this exercise, you will:

Understand the usage of variables

Learn about the techniques to create variables, modify value and use of variables

Scenario
The Windows PowerShell variable provider allows you to create, add, and delete variables.
First, let us understand what a variable is. A variable, as the name suggests, is something
whose value can vary.
Variables are primarily used for two reasons:
1. To hold some value or data in memory
2. To hold the output, which is a result of an expression
Variables can store information about different types such as string, integer, and Boolean.
The various types will be discussed later in this lesson.
In the exercise below, the following operations will be demonstrated using variables:

Variable assignment

Variable expansion

Variable related Cmdlets

Task 1: Log on to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Variable Assignment


In PowerShell, you can create a variable name by adding a $ sign before the name of the
variable.
1. To create a variable of name, Result, add $ sign before it and use an equals sign to assign
it a value. Thus, the name of the variable will be $Results.
PS C:\> $Results = We won!

You can use the New-Variable built in Cmdlet as well, to create a new variable. When
using the New-Variable Cmdlet, you do not need to add a $ sign before the variable name.
2. To create a variable using the New-Variable Cmdlet, type the following command:
PS C:\> New-Variable Results2 value We won again!

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 141 of 361

3. Write an expression that performs a compare operation and stores the result of the
operation inside a variable.
The expression will be evaluated to either True or False. The expression would be as
follows:
PS C:\> $a = 5
PS C:\> $b = 6

Creating a new variable and assigning the value of 5.


Creating a new variable and assigning the value of 6.

4. Create a third variable to store the value of the expression.


Let the name of that variable be $c.
PS C:\> $c = ($b -gt $a)
PS C:\>$c

-gt in Windows PowerShell is a comparison operator for "Greater Than". In this case, the
expression evaluates to true.
The result will be stored in the variable $c. Note the Type of the variable, $c.
PS C:\> $c.GetType()
IsPublic IsSerial Name
-------- -------- ---True
True
Boolean

BaseType
-------System.ValueType

It is Boolean since we have a value of True of False.


PS C:\> $a.gettype()
IsPublic IsSerial Name
-------- -------- ---True
True
Int32

BaseType
-------System.ValueType

It is an Integer since we have an integer value.

A "Type" is what defines the kind of information or value that can be stored in a variable.
Note: A variable name can also have spaces in between however; remember to
enclose the variable name inside a curly brace.

For example, ${New Variable}.

Automatic Variables
Although you can choose a name of your choice for a variable, there are certain special
variables that are predefined in PowerShell.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 142 of 361

The following are some of the automatic variables that are predefined in Windows
PowerShell. These variable names are reserved.
$Args

Stores values of parameters passed to a function

$Error

Stores information about the error object when an error has occurred during
any script execution

$PsHome

Home directory where the PowerShell is installed

$Home

Home directory of the user

$True

Check for Boolean Value of True

$False

Check for Boolean Value of False

Note: For a complete list of automatic variable, refer the Online Help.

Variable Expansion
Quotes have a special meaning when used with variables.
Consider the following example:
PS C:\> $First = Hello
PS C:\> $Statement1 = $First World
PS C:\> $Statement1
Hello World

The output stored in the variable $Stament1 will be Hello World. This is because, when you
use double quotes, Windows PowerShell will expand the variable name with its value.
In the example, you can see that the output is Hello World. This is because, Windows
PowerShell substitutes $First with its value, which is Hello.
On the other hand, if you assign the values within single quotes, Windows PowerShell takes
that as a literal value and does not substitute the value. Consider the following example,
PS C:\> $First = Hello
PS C:\> $Statement1 = $First World
PS C:\> $Statement1
$First World

You can see in this example that the value of $First is not inserted into $Statement1
We learnt about variables in this section however, there might be situations where we need to
constant value. We can define a constant using Set-Variable Cmdlet.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 143 of 361

Variable Related Cmdlets


To work with variables using the variable provider, the following Cmdlets are built in
Windows PowerShell.
Get-Variable

Gets the variables in the current console

New-Variable

Creates a new variable

Set-Variable

Sets the value of a variable

Remove-Variable

Deletes a variable and its value

Clear-Variable

Deletes the value of a variable

Task 3: Expressions
Windows PowerShell executes the command depending on the command input. If a native
Windows command was typed, PowerShell will execute the command in a way similar to
how Windows would execute in a CMD command shell.
Similarly, if you write a mathematical or a comparison expression in the PowerShell console,
it will process accordingly.
1. Type the following command in the PowerShell console:
PS C:\> ipconfig.exe
Windows IP Configuration
Connection-specific DNS
IPv4 Address. . . . . .
Subnet Mask . . . . . .
Default Gateway . . . .

Suffix
. . . .
. . . .
. . . .

.
.
.
.

:
: 192.168.1.1
: 255.255.255.0
: 0.0.0.0

Wireless LAN adapter Wireless Network Connection:


Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :contoso.com
Ethernet adapter Local Area Connection:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :contoso.com
Tunnel adapter isatap.corp.microsoft.com:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :

This behavior of PowerShell is also known as Argument mode processing.


2. Using a PowerShell cmdlet, we can see similar behavior with arguments by running the
following command in the console:
PS C:\> Write-Host 6*5
6*5

Because PowerShell is in argument parsing mode, it interprets 6*5 as an expression


and displays it to the console host.
3. Now, type the following command in the PowerShell console:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 144 of 361

PS C:\> Write-Host (6*5)


30

After processing Write-Host, PowerShell encounters the ( which causes it to switch to


expression mode parsing. In this expression mode, it actually evaluates the mathematical
expression of 6*5 and the output is 30.
4. The dollar sign is another one of the common characters that can cause PowerShell to
enter expression mode parsing.
$int = 5 + 5
$int

You can see now that instead of treating the line of text as a command, PowerShell sees
the dollar sign and knows that this is an expression to be evaluated, one which assigns the
value of 5+5 into the variable int. On the second line, the evaluation is simply to
retrieve the variable, which causes PowerShell to output that variable to the pipeline.
5. You can also force PowerShell into argument mode on a given expression. Enter the
following commands:
$cmd = get-command
$cmd

We are simply using expression parsing mode and assigning a string into a variable.
Note that the get-command cmdlet is not actually executing, this is merely a text
assignment.
6. Using the ampersand, also known as the call operator, we can now force the previous
expression to be evaluated in argument mode instead.
&$cmd

This time the output is the same as if you directly executed the get-command cmdlet.
7. Script blocks are another example where PowerShell changes between parsing modes.
Execute the following code:
{ get-command verb get }

This simply defines a script block, but does not execute it.
8. You can execute the code by putting the call operator in front of it:
& {get-command -Verb get}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 145 of 361

Exercise 2: Basic Variable Types in PowerShell


Objectives
In this exercise, you will:

Understand the type fundamentals in Windows PowerShell

Learn the use of specific types of variables

Scenario
In PowerShell, you can create and delete objects for various purposes. In those objects, you
can store data for performing some operations. Before you can store data, you may define the
kind of data to be stored in that object. The kind of information that can be stored in an object
is defined by its "Type".
Let us look at a few examples to understand this in detail.
In the exercise that follows, the use of different Types will be demonstrated.

Number types

String types

Expandable strings

Literal strings

Here-strings

Other types

Task 1: Log on to VM Environment


Log on to the Windows 7 client as Contoso\Administrator.
In Windows PowerShell, some common "Types" are defined for Integer, Strings, and
Boolean.

Task 2: Number Type


To understand numeric type, consider the following example:
To launch PowerShell, click

on the taskbar.

1. Create a variable named, a and assign the value 9.


PS C:\> $a = 9

2. Here, you create a new variable and store a value of 9 in it. Now, let us see the type of
variable.
3. To find the type of variable, use the GetType() method.
PS C:\>$a.gettype()
IsPublic IsSerial Name
-------- -------- ----

Microsoft | Services

BaseType
--------

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 146 of 361

True

True

Int32

System.ValueType

4. Note the name, Int32. To hold the value, 9, you created an instance of "Type" of Int32
object. An Int32 object represents a 32-bit integer.
5. Change the value of the variable from an integer to a floating point.
PS C:\> $a = 4.5
PS C:\> $a.gettype()
IsPublic IsSerial Name
-------- -------- ---True
True
Double

BaseType
-------System.ValueType

Note the Name property. It changed from Int32 to Double. An instance of "Type" of
Double object represents a floating-point number.
6. Assign a larger value to the same variable.
PS C:\> $a =8000000000
PS C:\> $a.gettype()
IsPublic IsSerial Name
-------- -------- ---True
True
Int64

BaseType
-------System.ValueType

Note that the Name property now shows Int64.


Let us take a few more examples. This time rather than assigning a math value let us take
a list of all services on the computer.
7. In the PowerShell console, type the following command:
PS C:\> $a = Get-Service
PS C:\> $a.gettype()
IsPublic IsSerial Name
-------- -------- ---True
True
Object[]

BaseType
-------System.ValueType

8. Similarly, store True or False in a Boolean object Type.


PS C:\> $a = 1
PS C:\> $b = 2
PS C:\> $c = ($a -lt $b)
PS C:\> $c
True
PS C:\> $c.gettype()
IsPublic IsSerial Name
-------- -------- ---True
True
Boolean

Microsoft | Services

BaseType
-------System.ValueType

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 147 of 361

In the example above, you created two variables initially, assigned values to it and then did a
compare operation. To store the result of the compare operation, you created a third variable
and you can see that the "Type" is Boolean.

Task 3: String Type


PowerShell allows storing strings in variables. A string is a collection of characters. In the
previous section, we looked at the different number types. In this section, you will get
familiar with string types and their use.

Expandable Strings
String expansion is a very important functionality in Windows PowerShell. Consider an
example to understand this behavior.
In the following example, you will understand the significance of quotes with variables:
1. Create a new variable name and assign the string value Bob in double quotes.
2. Use the same variable with a statement enclosed in double quotes.
PS C:\> $name = "Bob"
PS C:\> "Hi $name, Welcome to the PowerShell workshop"
Hi Bob, Welcome to the PowerShell workshop

You can notice that when the string was in double quotes, you substituted the variable
$name with its value. This behavior is called string expansion.
3. Now, try the same using single quotes.
When the statement is enclosed with a Single quote, we see that the variable is not
substituted with its value.
PS C:\> 'Hi $name, Welcome to the PowerShell workshop'
Hi $name, Welcome to the PowerShell workshop

Literal Strings
4. To assign a string value to the variable, type the following command:
PS C:\>

$a = "Welcome to the world of PowerShell!"

PS C:\> $a
Welcome to the world of PowerShell!
PS C:\> $a.GetType()
IsPubli IsSerial Name
-------- -------- ---True
True
String

BaseType
-------System.ValueType

You now stored a Literal string.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 148 of 361

5. To store a string value in a variable, use either a single quote or a double quote.
PS C:\> $a = "Welcome to the world of PowerShell!"
PS C:\> $a
Welcome to the world of PowerShell!

PS C:\> $a = 'Welcome to the world of PowerShell!'


PS C:\> $a
Welcome to the world of PowerShell!

In this case, both yield the same results for a simple assignment.

Here Strings
A Here string is used to place a sequence of strings the way they are, without any additional
formatting.
Consider an example.
6. Create another variable and assign the string value exactly as shown below.
PS C:\> $NewString = "Hello and how are you?"
PS C:\> $NewString
Hello and how are you?

You can see the output without any additional formatting.


Consider another example to display the following statement as an output:
"Good Morning!, how are you?", would you like to have a cup of tea or coffee?
7. Create a new variable named ComplicatedString, and assign the string value as shown
below and observe the behavior.
PS C:\> $ComplicatedString = ""Good Morning!, how are you?", would you like to
have a cup of tea or coffee?"
Unexpected token 'Good' in expression or statement.
At line:1 char:28
+ $ComplicatedString = ""Good <<<< Morning!, how are you?", would you like to
have a cup of tea or coffee?"
+ CategoryInfo
: ParserError: (Good:String) [],
ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
PS C:\> $ComplicatedString = ""Good Morning!, how are you?", would you like to
have a cup of tea or coffee?""
Unexpected token 'Good' in expression or statement.
At line:1 char:28
+ $ComplicatedString = ""Good <<<< Morning!, how are you?", would you like to
have a cup of tea or coffee?""
+ CategoryInfo
: ParserError: (Good:String) [],
ParentContainsErrorRecordException

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 149 of 361

+ FullyQualifiedErrorId : UnexpectedToken
PS C:\> $ComplicatedString = "Good`Morning!, how are you?", would you like to have
a cup of tea or coffee?"
Missing expression after ','.
At line:1 char:52
+ $ComplicatedString = "Good`Morning!, how are you?", <<<< would you like to have
a cup of tea or coffee?"
+ CategoryInfo
: ParserError: (,:String) [],
ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingExpressionAfterToken

You can make this work by adding a few correct quotes and braces, but it is time
consuming. In such a case, Here string is useful.
8. In PowerShell, type the following command:
PS C:\> $ComplicatedString = @
>> Good Morning!How are you?, would you like to have a cup of tea or a coffee?
>> "@
>>
PS C:\> $ComplicatedString
Good Morning!How are you?, would you like to have a cup of tea or a coffee?
PS C:\>

The string included between the start and the end of the Here string is displayed as it is.
Windows PowerShell does not parse any quotes or braces inside a Here string. Hence, the
string is stored without any errors.

Other Types
You looked at some of the basic primitive number and string types. However, Windows
PowerShell has more types available in it. The following table from TechNet shows the
various types.
Data Type Alias

Type Description

.Net Framework Type

[int]

32-bit signed integer

System.int32

[long]

64-bit signed integer

System.int64

[string]

Fixed-length string of Unicode


characters

System.String

[char]

Unicode 16-bit character

System.char

[bool]

True/false value

System.Boolean

[byte]

8-bit unsigned integer

System.byte

[double]

Double-precision 64-bit floating


point number

System.Double

[decimal]

128-bit decimal value

System.Decimal

[single]

Single-precision 32-bit floating


point number

System.Single

[array]

Array of values

System.Array

[xml]

Xmldocument object

System.Xml.XmlDocument

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 150 of 361

[hashtable]

Hashtable object (similar to a


Dictionary object)

System.Collections.Hashtable

[object]

Generic object type

System.Object

Data type Aliases and type qualification.


The above table contains what are called data type aliases. These are used as a shortcut
instead of typing the whole .NET framework types when in PowerShell. There are many
more data type aliases available. However, the table above does cover most of the common
alias that you will encounter. It is also possible to create your own data type aliases but this
will not be covered here.
A common use of the datatype aliases is to use them to qualify either data as a certain type or
to type constrain a variable.
Normally in powershell you are not too concerned with the types of a variable or data. This is
due to the type adaption system that powershell uses which converts the type when needed.
However, there are some circumstances that might require the types to be qualified. To do
this with PowerShell, you use the data type aliases.

Data qualification
Using the data type aliases on the right hand side of the assignment operator allows for the
data to be qualified, or cast as a specific type.
1. Type the following in the PowerShell console to create a variable
$a = 77

2. Type the following to check the type


$a.gettype()

You will see that you have an int32


3. Type the following create a variable
$a = 77

4. Type the following to check the type


$a.gettype()

You will see that you have a string.


5. Type the following to qualify the data as a int32
$a = [int] 77

6. Type the following to check the type


$a.gettype()

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 151 of 361

You will see that you have an int32. This is due to qualifying, or casting the data as a number.
However, the variable can still be set to a string or any other type as the variable has not been
type constrained.
7. Type the following to set $a to a string
$a = See I can still be a string

8. Type the following to check the type


$a.gettype()

You will see that you have a string.

Type constraining
As well as being able to qualify data as a specific type, it is possible to also constrain a
variable to be a specific type. This is done by using the data type alias on the left hand side of
the assignment operator. This means that the variable will only be able to contain data of that
specific type. If you try to assign a different type to that variable it will fail.

1. Type the following in the PowerShell console to create a variable


$a = 77

2. Type the following to check the type


$a.gettype()

You will see that you have an int32


3. Type the following create a type constrained variable
[int]$a = 77

4. Type the following to check the type


$a.gettype()

You will see that you have an int3 even though a string of 77 was assigned .
5. Type the following to assigned a string to the variable
$a = this will not work

You will now see that you get an error from PowerShell. This is because the string this will
not work cannot be converted to an int32. This is because we can only store numbers in the
variable due to the type constraint.
6. Type the following to assign another number to the variable
$a=42

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 152 of 361

This will work as 42 is an int32.


Is it possible to change the constraint on the variable to another type.
7. Type the following to constrain $a to a string
[string]$a = See I can now be a string

8. Type the following to check the type


$a.gettype()

You will see that you have a string. If you try to now assign a number this will now fail.
9. Type the following to assign an int32 to $a
$a = 42

You will now see that this succeeds because converting an integer to a string is allowed.
10. You can also effectively remove the constraint from a variable by making it of type
object. Type the following to qualify the variable as type object
[object]$a = 42

11. Type the following to check the type


$a.gettype()

You will see that you have an int32.


12. Type the following to assigned a string to the variable
$a = this works now

13. Type the following to check the type


$a.gettype()

You will see that you have a string.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 153 of 361

Exercise 3: Working with Arrays


Objectives
In this exercise, you will:

Understand the use of an Array in Windows PowerShell.

Learn how to create, modify values in an Array and add Elements in an Array.

Scenario
In the previous exercise, you learnt about the use of variables and the type fundamentals in
PowerShell. Let us continue to explore the functionality and use of arrays in this module.
An array object contains a collection of elements of the same type. For example, an array of
integers or string.
While evaluating any expression, the output can be either a single object or a collection of
objects.
To store the result of all services on a computer, you create an array.
The following is an illustration of a simple one-dimensional array.

Each block is referred to as an element, which stores values.


Arrays can be one-dimensional or multi-dimensional. The following is an illustration of a
two-dimensional array.

Task 1: Log on to VM Environment


Log on to the Windows 7 client as Contoso\Administrator.

Task 2: Create Arrays


1. To create an array object, directly assign the element values delimited with a comma to
the array variable.
PS C:\> $NewArray = a,b,c
PS C:\> $NewArray.Gettype()
IsPublic IsSerial Name
-------- -------- ---True
True
Object[]

BaseType
-------System.Array

2. We can also create an empty array using the @ operator.


PS C:\>$NewArray = @()

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 154 of 361

Let us look at creating an array of numbers.


3. In the PowerShell console, type the following command to create an array. Notice the
values of elements.
PS C:\> $Numbers = @(1,2,3,4,5)
PS C:\> $Numbers
1
2
3
4
5
PS C:\> $Numbers.gettype()
IsPublic
-------True

IsSerial
---------True

Name
------------Object[]

BaseType
-----------System.Array

4. Use the Get-Service Cmdlet to get a list of all services running on a computer and store
the output in $service as an array.
PS C:\> $service = get-service
PS C:\> $service
Status
-----Stopped
Stopped
Stopped
Running
Stopped
Stopped
Running
Running

Name
---AeLookupSvc
ALG
AppIDSvc
Appinfo
AppMgmt
aspnet_state
AudioEndpointBu...
AudioSrv

DisplayName
----------Application Experience
Application Layer Gateway Service
Application Identity
Application Information
Application Management
ASP.NET State Service
Windows Audio Endpoint Builder
Windows AudioPS C:\> $Numbers.gettype()

IsPublic IsSerial Name


-------- -------- ---True
True
Object[]

BaseType
-------System.Array

PS C:\>

Task 3: Add Elements to Arrays


In the example that follows, you will see how you can add elements in an array. Create a
variable named $numbers, which will store numbers from 1 to 10.
1. In the PowerShell console, type the following command:
#Create an array and assign values to elements.
PS C:\> $numbers = 1,2,3,4,5,6,7,8,9,10
PS C:\> $numbers.count
10

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 155 of 361

The count property of array tells us how many elements are present in an Array.
2. To add an element and assign a value, type the following command:
PS C:\> $numbers += 11
PS C:\> $numbers
1
2
3
4
5
6
7
8
9
10
11
PS C:\> $numbers += 12
PS C:\> $numbers.Count
12
PS C:\>PS C:\>

The count of the array has increased since you added two elements.

Task 4: Array Addressing


In an array, the first element is referred as index 0.
1

10

The array holds values for 10 elements. To find the value in the first element, which is 1,
refer the index number 0.
In the following example, a variable named $numbers stores the numbers 1 to 10.
Take a count of how many elements you have in the array. Modify the value of the first
element in the array.
#Create an array and assign values to elements.
PS C:\> $numbers = @(1,2,3,4,5,6,7,8,9,10)
PS C:\> $numbers.count
10

# Changing the value of 1st element from 1 to 11.


PS C:\> $numbers[0]= 11
PS C:\> $numbers
11
2
3
4
5
6

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 156 of 361

7
8
9
10
PS C:\>

In an array, you can use the index number to refer to individual elements.
$a[0]

This will display the value of the 1st element.

$a[1]

This will display the value of the 2nd element.

$a[-1]

This will display the value of the last element in


array.

$a[-2]

This will display the value of the second last


element in array.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 157 of 361

Exercise 4: Working with Hash Tables


Objectives
In this exercise, you will:

Understand the techniques of creating and accessing different values in Hash table

Learn how Hash tables can be used while building scripts

Scenario
Hash table is a kind of array where we can store the values in a key-value pair.
Hash tables are used when we need to store information in the form of a dictionary array and
then access the value of an element using a corresponding label name.
The following is an example of an array representing the ID of employees within an
organization:
Dave

183

Roy

478

Alice

671

In this module, the following operations for hash tables will be discussed.

Creating hash tables

Adding to hash tables

Hash table addressing

Task 1: Log on to VM Environment


Log on to the Windows 7 client as Contoso\Administrator.

Task 2: Create Hash Tables


Creating a hash table is similar to creating an array except one difference.
In an array, elements are inside parenthesis (), and in hash tables, elements are inside braces
{}.
$Numbers = @{"A"=1; "B"=2; "C"=3}
$Numbers.GetType()

Let us look at a hash table, which contains employee name and ID.
1. In the PowerShell console, type the following command to create a hash table.
$a = @{"Dave"=123; "Roy"=478; "Alice"=671}
$a
Name
---Dave

Microsoft | Services

Value
----183

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 158 of 361

Roy
Alice

478
671

Task 3: Add Entries to Hash Tables


In the below example, we are creating a Hash table which will store the information about the
computer type.
Note: The order of your keys/value pairs may show up sorted differently than the
exercises below, this is normal behavior because hash tables are not ordered.

1. In the PowerShell console, type the following command to create a hash table:
$ComputerType = @{"Type1"="Desktop";"Type2"="Server";"Type3"="Laptop"}
$ComputerType
Name
---Type1
Type2
Type3

Value
----Desktop
Server
Laptop

Add a New Entry to Hash Table


2. In the PowerShell console, type the following command to add a new entry to a hash
table:
$ComputerType[Type4] =TabletPC
$ComputerType
Name
---Type1
Type2
Type3
Type4

Value
----Desktop
Server
Laptop
TabletPC

3. In the PowerShell console, type the following command to add a new entry to a hash
table:
$computertype.Type5=Slate
Name
---Type1
Type2
Type3
Type4
Type5

Value
----Desktop
Server
Laptop
TabletPC
Slate

4. In the PowerShell console, type the following command to change the value of an
existing key:
$ComputerType[Type4] =Netbook
$ComputerType

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 159 of 361

Name
---Type1
Type2
Type3
Type4
Type5

Value
----Desktop
Server
Laptop
Netbook
Slate

Task 4: Hash Table Addressing


Addressing hash tables is different from addressing an array. Although, both have elements,
when you address a specific value of a key in a hash table, you address using the Key Name.
1. Consider the following hash table:
$a = @{"Dave"=123; "Roy"=478; "Alice"=671}
$a
Name
---Dave
Roy
Alice

Value
----183
478
671

2. From the example, to find the ID of Dave, address it as follows:


$a.Dave
183
$a.Roy
478
$a.Alice
671

According to the definition, this table contains a Key-Value pair. Every key will have an
associated value to it and you can address the value by using a dot reference to its key.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 160 of 361

Exercise 5: Working with Console Input-Output


Objectives
In this exercise, you will:

Understand Windows PowerShell console Input-Output

Understand various methods of interacting with PowerShell console for Input-Output


operations

Scenario
Like every other scripting and programming environment, Windows PowerShell offers
variety of methods from where an input can be passed for a command to be executed as well
as to display the results.
The Windows PowerShell console host is where the command you type is by default, used to
take the user input and to display the output.
First, let us look at the input mechanisms in Windows PowerShell.
The following is a sample script that prompts a user to enter a valid path. After the path is
entered, scan the directory to get only the files inside that directory.

Console Input
============
Script code:
============
$Path = Read-Host "Please enter a valid path"
$obj = @(dir $path)
$objcount = $obj.count
for ($i = 0; $i -lt $objcount; $i++)
{
if ($($obj[$i].Length))
{
$obj[$i].Name
}
}

In this code, a Cmdlet, Read-Host that prompts a user for an input is used. Based on the input,
the script will be processed further.
While using the Cmdlet is one way of passing an Input to PowerShell, the PowerShell
console Host also takes a user input and processes the commands.

Console Output
You might have noticed that whenever you type a command in the PowerShell console, you
see the output in the command window.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 161 of 361

This is because of the Out-Default Cmdlet that is executed after every Cmdlet. Therefore, in
the PowerShell console, whenever you execute a command, Get-Service, PowerShell is
actually executing the command Get-Service | Out-Default.
Out-Default will send the output to Out-Host and then the output is displayed on the host
window.
Additional options to specify output to a specific object:
Out-File

Will send an output to a file

Out-Printer

Will send an output to a printer

Out-Host

Default output window

Out-Grid

Display the output in a Grid view

Write-Host

Writes customized output to a host

Write-Output

Sends the specified objects to the next command


in the pipeline.
If the command is the last command in the
pipeline, the objects are displayed in the console.

Tee-Object

Microsoft | Services

Saves command output in a file or variable, and


displays it in the console

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 162 of 361

Exercise 6: Working with Files


Objectives
In this exercise, you will:

Understand management of files and folders using Windows PowerShell

Explore various built-in Cmdlets used for File Management

Scenario
Windows PowerShell adds functionalities to manage files and folders on a local as well as a
remote computer.
Administrators can perform a variety of operations for files and folder management such as
create, delete, rename, copy, and move.

Task 1: Log on to VM Environment


Log on to the Windows 7 client as Contoso\Administrator.
1. Run a simple command to verify the existence if a file. Use the Test-Path Cmdlet.
test-path C:\Windows\system32
True

You can see that the result is True as you know that the folder does exist.
2. Type the following command to verify the existence of another folder:
test-path C:\Windows\system32\anotherwindows
False

As expected, the result is false as there is no folder with the name anotherwindows.
3. Type the following command to see how you can implement the simple test as an
important check in script:
$Fileinfo = Test-Path C:\Windows\System32\drivers\ntfs.sys
if ($Fileinfo -eq "True") {Write-Host "File Exists"}
File Exists

When this is executed, observe the output. You can also add another condition to write
File Does not exist, if it does not.
PowerShell also allows copying or moving files from one location to another. In the
following example, you will copy a file from C:\ to D:\ using the following command.
Copy-Item C:\pshell\part1\lesson5\setup.log C:\pshell\part1\lesson5\newsetup.log

4. Run the following Cmdlet to move the file from one location to another.
Move-Item C:\pshell\part1\lesson5\setup.log c:\temp -force

You can also delete, or rename files using the Delete-Item, or Rename-Item Cmdlets.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 163 of 361

Alternatively, you can use these methods on a file or directory object to copy, move, or
delete.
$file = Get-Item C:\pshell\part1\lesson5\setup.log
$file | gm membertype method
TypeName: System.IO.FileInfo
Name
---AppendText
CopyTo
Create
CreateObjRef
CreateText
Decrypt
Delete
Encrypt
Equals
GetAccessControl
GetHashCode
GetLifetimeService
GetObjectData
GetType
InitializeLifetimeService
MoveTo
Open
OpenRead
OpenText
OpenWrite
Refresh
Replace
SetAccessControl
ToString

MemberType
---------Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method

Definition
---------System.IO.StreamWriter AppendText()
System.IO.FileInfo CopyTo(string destFi...
System.IO.FileStream Create()
System.Runtime.Remoting.ObjRef CreateOb...
System.IO.StreamWriter CreateText()
System.Void Decrypt()
System.Void Delete()
System.Void Encrypt()
bool Equals(System.Object obj)
System.Security.AccessControl.FileSecur...
int GetHashCode()
System.Object GetLifetimeService()
System.Void GetObjectData(System.Runtim...
type GetType()
System.Object InitializeLifetimeService()
System.Void MoveTo(string destFileName)
System.IO.FileStream Open(System.IO.Fil...
System.IO.FileStream OpenRead()
System.IO.StreamReader OpenText()
System.IO.FileStream OpenWrite()
System.Void Refresh()
System.IO.FileInfo Replace(string desti...
System.Void SetAccessControl(System.Sec...
string ToString()

File.CopyTo(C:\temp\Newlog.txt)

The CopyTo method copies the file to the specified location.

Task 2: Read from Files


1. Use the get-Content Cmdlet to read the content from a file as follows:
Get-Content C:\pshell\part1\lesson5\setup.log
[InstallShield Silent]
Version=v7.00
File=Log File
[ResponseResult]
ResultCode=0
[Application]
Name=Integrated Camera Driver Installer Package Ver.1.1.0.42
Version=1.1.0.42
Company=RICOH
Lang=0009
VersionInfo

2. You can also clear the contents of file using the Clear-Content Cmdlet as follows:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 164 of 361

Clear-Content C:\pshell\part1\lesson5\setup.log

Task 3: Write to Files


In the following examples, you will look at the Cmdlets you can use to write something to a
file. You will use the Set-Content and Out-File Cmdlets.
1. In the PowerShell console, type the below command to write the word Hello to a file in
drive D and the filename is test1.txt.
Set-Content C:\pshell\part1\lesson5\test1.txt "Hello"

2. Run the Get-Content Cmdlet, to verify the content of the text file.
Get-Content C:\pshell\part1\lesson5\test1.txt
Hello

3. You may want to write entire output of a Cmdlet to a file. For example, the status of all
the services running on a computer, list of all the running process etc.
4. This can be achieved using the Out-File Cmdlet as follows:
Get-Service | Where-Object {$_.status -eq "Running"} | Out-File `
-FilePath "C:\pshell\part1\lesson5\Services.txt"
Get-Content C:\pshell\part1\lesson5\Services.txt
Status
-----Running
Running
Running
Running
Running
Running
Running
Running
Running
Running

Name
---Appinfo
AudioEndpointBu...
AudioSrv
BDESVC
BFE
BITS
bthserv
btwdins
CcmExec
CertPropSvc

DisplayName
----------Application Information
Windows Audio Endpoint Builder
Windows Audio
BitLocker Drive Encryption Service
Base Filtering Engine
Background Intelligent Transfer Ser...
Bluetooth Support Service
Bluetooth Service
SMS Agent Host
Certificate Propagation

Task 4: Work with Other File Formats


PowerShell allows saving data in different formats such as HTML, CSV, and XML. You can
use the Cmdlets on many occasions to read the content from a .txt file and get the output in an
HTML format to present it as a report.
1. Let us look at an example to create a report of all the running services on computer.
Get-Service | Where-Object {$_.status -eq "Running"} | ConvertTo-Html Name, `
Status | Set-Content C:\pshell\part1\lesson5\Services.html
invoke-item C:\pshell\part1\lesson5\Services.html

The following is the output when the file is converted to HTML.


Name

Status

Appinfo

Running

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 165 of 361

AudioEndpointBuilder

Running

AudioSrv

Running

BDESVC

Running

BFE

Running

BITS

Running

Bthserv

Running

btwdins

Running

CcmExec

Running

The first Cmdlet gets a list of all the services of the system.
Then we pipe that output and take a look at the status property of each object to match if
it is "Running".
Then, we use the ConvertTo-HTML Cmdlet to covert the output.
The end part, Set-Content Cmdlet writes the content to the file.
PowerShell also adds the flexibility to export the content to a CSV file. We can use the
Export-CSV Cmdlet to export the output to a CSV file
2. Consider another example.
Get-Service | Where-Object {$_.status -eq "Running"} | Export-CSV `
C:\pshell\part1\lesson5\Services.csv
notepad c:\pshell\part1\lesson5\services.csv

The code above exports the output to a CSV file and loads it.
3. One last example deals with saving content in a much more rich format: XML.
Get-Service | Where-Object {$_.status -eq "Running"} | Export-clixml `
C:\pshell\part1\lesson5\Services.xml
Invoke-item C:\pshell\part1\lesson5\Services.xml

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 166 of 361

Exercise 7: PowerShell Error Object


Objectives
In this exercise, you will:

Understand the use of PowerShell error object

Explore different variables available to store the error information

Understand how PowerShell error object can be used for effective debugging

Scenario
It is common for an administrator, writing a script to encounter an error during the execution.
PowerShell provides a rich set of inbuilt objects and mechanisms to understand the error
details and then take the necessary corrective actions.

Task 1: Log on to VM Environment


Log on to the Windows 7 client as Contoso\Administrator.
1. Launch the PowerShell console and type the following command:
Get-Process invisibleapp.exe
Get-Process : Cannot find a process with the name "invisibleapp.exe". Verify the
process name and call the Cmdlet again
At line:1 char:12
+ Get-Process <<<< invisibleapp.exe
+ CategoryInfo
: ObjectNotFound: (invisibleapp.exe:String) [GetProcess], ProcessCommandException
+ FullyQualifiedErrorId :
NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand

The error on the console host can be viewed. In Windows PowerShell, there is an Error object
of type, System.Management.Automation.ErrorRecord.
The automatic variable $Error contains information about the most recent errors.
$error
Get-Process : Cannot find a process with the name "invisibleapp.exe". Verify the
process name and call the Cmdlet again
At line:1 char:12
+ Get-Process <<<< invisibleapp.exe
+ CategoryInfo
: ObjectNotFound: (invisibleapp.exe:String) [GetProcess], ProcessCommandException
+ FullyQualifiedErrorId :
NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand

Like other array objects, you can take a count of the errors currently stored in the error object.
$error.count
1

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 167 of 361

Since this is implemented as an array, use the traditional method to refer to index 0 for the
value of the first element.
Below you can see some examples of what errors may look like, but your environment will
likely be very different.
$error[0]
Get-Process: Cannot find a process with the name "invisibleapp.exe". Verify the
process name and call the Cmdlet again
At line:1 char:12
+ Get-Process <<<< invisibleapp.exe
+ CategoryInfo
: ObjectNotFound: (invisibleapp.exe:String) [GetProcess], ProcessCommandException
+ FullyQualifiedErrorId :
NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
$error[1]
The term 'lastexistcode' is not recognized as the name of a Cmdlet, function,
script file, or operable program. Check t
he spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:1 char:14
+ lastexistcode <<<<
+ CategoryInfo
: ObjectNotFound: (lastexistcode:String) [],
CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
$error[2]
Get-Item : A positional parameter cannot be found that accepts argument 'Exit'.
At line:1 char:9
+ Get-Item <<<< c:\doentexist.txt Exit 123
+ CategoryInfo
: InvalidArgument: (:) [Get-Item],
ParameterBindingException
+ FullyQualifiedErrorId :
PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetItemCommand
$error[3]
Get-Item : Cannot find path 'C:\doentexist.txt' because it does not exist.
At line:1 char:9
+ Get-Item <<<< c:\doentexist.txt
+ CategoryInfo
: ObjectNotFound: (C:\doentexist.txt:String) [GetItem], ItemNotFoundException
+ FullyQualifiedErrorId :
PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

By default, you can store up to 256 errors in the $Error object. This is implemented using the
$MaximumErrorCount variable.
However, the value for the variable in the example can be changed.
It is also possible to clear the error variable. You can do this by using the clear method on the
error variable. This is a good idea to use when scripting with PowerShell. This enables you to
focus only on the errors that your scripts has generated, not errors that might have been
produced outside of the current script.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 168 of 361

Type the following to clear the variable


$error.clear()

Error Variable Parameter


Windows PowerShell provides an option of recording the error information for a specific
Cmdlet using the $ErrorVariable parameter.
get-process -id 112 -ErrorVariable Errprocess
Errprocess
Get-Process : Cannot find a process with the process identifier 112.
At line:1 char:12
+ get-process <<<< -id 112 -ErrorVariable Errprocess
+ CategoryInfo
: ObjectNotFound: (112:Int32) [Get-Process],
ProcessCommandException
+ FullyQualifiedErrorId :
NoProcessFoundForGivenId,Microsoft.PowerShell.Commands.GetProcessCommand

Task 2: Determine Last Exit Code


The last exit code of the script or the Windows based program can be determined using the
$LastExitCode automatic variable.
To find the result of the executed script or command, use the $? Variable.
To understand this further, consider two more variables.
1. Open the PowerShell Command and ping a reachable IP address. In this case, ping the
loopback IP.
ping 127.0.0.1
Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time=3ms TTL=64
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
Reply from 127.0.0.1: bytes=32 time<1ms TTL=64
Ping statistics for 127.0.0.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 3ms, Average = 0ms
$LastExitCode
0

Here, the result of execution of the code was successful and hence, the last exit code is 0.
There can be a user defined exit code.
2. Type the following command to ping a non-existent IP address and observe the error.
ping 127.0.0.900
Ping request could not find host 127.0.0.900. Please check the name and try again.
$LastExitCode
1

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 169 of 361

Task 3: Check Execution Status


To know the execution status of the last operation, use the "$?" variable.
get-process qwertyuiop
get-process : Cannot find a process with the name "qwertyuiop". Verify the process
name and call the cmdlet again.
At line:1 char:1
+ get-process qwertyuiop
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo
: ObjectNotFound: (qwertyuiop:String) [Get-Process],
ProcessCommandException
+ FullyQualifiedErrorId :
NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand
$?
False

Windows PowerShell allows specifying how it may respond to non-terminating errors. The
preference is defined in the $ErrorActionPreference variable.
$ErrorActionPreference
Continue

Currently, the preference is set to Continue and will therefore display the error and continue
with the script execution.
The other possible values for this variable are:
SilentlyContinue
When the preference is set to SilentlyContinue, the flow of execution of script continues even
when an error is encountered and it does not display the error on the host.
1. In the powershell console type the following
$erroractionpreference = "SilentlyContinue

2. Type the following command which will fail, but will not display any output.
Get-item fakefile

Inquire
Prompts for a user action when an error is encountered.
Stop
Halts the script execution.

Cmdlet erroraction parameter


In addition to the error active preference variable, there is an error action parameter available
on cmdlets. This overrides the global error action preference for that specific command. This
is useful if you have a single command that may generate an error and you wish to handle
that specific command separately.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 170 of 361

3. In the powershell console type the following


$erroractionpreference = "Continue

4. Type the following command which will fail


Get-item fakefile

This above command will generate an error and display this.


5. Type the following to overwrite the error action for the specific command
Get-item fakefile erroraction silentlycontinue

You will note that the above does not display an error as per the previous command did.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 171 of 361

Lesson 5 Hands-On : Variables and Type


Fundamentals
Objectives
The objectives for this lab are:

To use different types of variables for various operations

To create, modify and understand use of an array

To create, modify and understand use of a hash table

Pre-requisites
The lab requires a Windows 7 client running in a domain environment.

Estimated Time to Complete this Lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 172 of 361

Exercise 1: Working with Variables


Objectives
In this exercise, you will:

Create variables for use with Numeric and string operations

Look at the different properties of the variable

Task 1: Log on the VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

. The PowerShell console opens.

Task 3: Work with Variables


1. type following command:
PS C:\> $x = 10

2. On the next line, type the following command:


PS C:\> $y = 45

You created two variables and assigned a value to it.


3. Now perform an addition operation.
PS C:\> $z = $x + $y

4. The output of this operation will be stored in a third variable, $z.


5. In the PowerShell console, type the following commands to view the output stored in $z
and to find the type.
PS C:\> $z
55
PS C:\> $z.GetType()

6. Identify the type of the object.


7. Create another variable $a and assign a string value to it.
PS C:\> $a = "Good Morning,

8. Create another variable $b and assign another string value.


PS C:\> $b = "How are you?

9. Create a third variable $c and add variables $a and $b.


PS C:\> $c = $a + $b

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 173 of 361

10. In the PowerShell console, type the following command to view the output stored in $c:
PS C:\> $c
Good Morning, How are you?

11. Verify the results. This addition operation is also called String Concatenation.
You will now use the variable to store a collection of objects.
12. In the PowerShell console, type the following command to get a list of all running
processes on a system:
PS C:\> $Process = Get-Process

13. On the next line, type $Process to view the output.


PS C:\> $Process

Close all instances of notepad except one. If notepad is not running, start it.

14. On the next line, type the following command to find an instance of a running process
and store the output in $ProcessNotepad variable:
PS C:\> $ProcessNotepad = Get-Process Notepad

15. Type $ProcessNotepad in the command to view the output.


PS C:\> $ProcessNotepad

16. Type the following commands to view the properties of the object stored in
$ProcessNotepad:
PS
PS
PS
PS

C:\>
C:\>
C:\>
C:\>

Microsoft | Services

$ProcessNotepad.Threads
$ProcessNotepad.CPU
$ProcessNotepad.Handles
$ProcessNotepad.Path

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 174 of 361

Exercise 2: Working with Arrays


Objectives
In this exercise, you will:

Learn how to create arrays and manipulate the values of elements in an array.

Task 1: Log on to VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

. The PowerShell console opens.

Task 3: Create an Array and modify the elements


1. In the PowerShell console, type the following command to create an array with three
elements:
PS C:\> $Currency = @("Dollar","Rupee", "Pound")

2. In the PowerShell console, type the following command to access the first element in the
array, and view the output:
PS C:\> $Currency[0]

3. In the PowerShell console, type the following command to access the last element in the
array, and view the output:
PS C:\> $Currency[-1]

4. In the PowerShell console, type the following command to add a new element to an
existing array:
PS C:\> $Currency += "Yen"

5. Type $Currency to verify the addition of element in array.


6. In the PowerShell console, type the following command to change the value of an
existing element:
PS C:\> $Currency[2] = "Peso"

7. Type $Currency to verify the change operation in the array.


$Currency

8. In the PowerShell console, type the following command to store the first 10 application
event logs:
PS C:\> $logs = get-eventlog application | Select-Object -First 10

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 175 of 361

9. In the PowerShell console, type the following command to view the properties and
methods for the first object of an array:
PS C:\> $logs[0] | Get-Member

10. In the PowerShell console, type the following command to identify the machine name on
which the event was generated:
PS C:\> $logs[0].MachineName

11. In the PowerShell console, type the following command to find the description:
PS C:\> $logs[0].Message

Task 4: Combine Two Arrays


1. In the PowerShell console, type the following command to create two arrays:
PS C:\> $Array1 = @(1,2,3,4,5)
PS C:\> $Array2 = @("Six", "Seven", "Eight", "Nine", "Ten")

Make sure that quotes are added for string values or else you may encounter certain errors.
2. In the PowerShell console, type the following command.
PS C:\> $ArrayCombined = $Array1 + $Array2

3. Display the results of $ArrayCombined


$ArrayCombined

Task 5: Create an Array of a Specific Type


1. In the PowerShell console, type the following command to create an array of integer
type:
PS C:\> [int[]]$Numbers = @(1,2,3,4,5)

2. Assign a string value to it and notice the behavior.


PS C:\> $Numbers += "Word"

Observe the behavior. It will error!

3. Add a number to the array.


$Numbers += 6

4. Display the contents


$Numbers

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 176 of 361

Exercise 3: Work with Hash Tables


Objectives
In this exercise, you will:

Learn how to create a hash table, access and modify the values

Task 1: Log on to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

. The PowerShell console opens.

Task 3: Create a Hash Table and work with values.


1. In the PowerShell console, type the following command to create a new hash table:
PS C:\>$NewHashTable = @{"Company"="Microsoft Corporation";"Street"="One Microsoft
Way";"City"="Redmond";"State"="WA"}

2. Type $NewHashTable to view the Key-Value pair.


3. In the PowerShell console, type the following command to find the value for Company:
PS C:\> $NewHashTable.Company

4. In the PowerShell console, type the following command to add a new key-value to this
table:
PS C:\> $NewHashTable["Telephone"] = "98052-7329"

You added a new key. However, the value added is incorrect. The value is not the
telephone number, but the PIN.
5. In the PowerShell console, type the following command to modify and assign the correct
value:
PS C:\> $NewHashTable["Telephone"] = "425-882-8080"

6. Type $NewHashTable to verify the correction.


7. In the PowerShell console, type the following command to view the output of the hash
table in a table format:
PS C:\> $NewHashTable | FT *

8. In the PowerShell console, type the following command to view the output in a list
format:
PS C:\> $NewHashTable | FL *

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 177 of 361

You can create a hash table to store a specific type of values (integer, string) by prefixing its
type before the name. Use the same method for creating arrays of specific type.
9. In the PowerShell console, type the following command to sort the output by value:
PS C:\> $NewHashTable.GetEnumerator() | Sort Value

10. In the PowerShell console, type the following command to sort the output by name:
PS C:\> $NewHashTable.GetEnumerator() | Sort Name

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 178 of 361

Exercise 4: Work with Hash Tables and Calculated


Object Properties
Objectives
In this exercise, you will:

Learn how to use calculated object properties with hash tables

Task 1: Log on to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

. The PowerShell console opens.

Task 3: Working with Hash Tables and Calculated Object properties.


1. Launch two or three instances of Notepad with an interval of 30 seconds for each
instance.
2. In the PowerShell console, type the following command to create a hash table and format
the output using the Format-Table Cmdlet:
PS C:\> PS C:\> get-process notepad | Format-table
Handles
------65
65
65

NPM(K)
-----7
7
7

PM(K)
----2572
2568
2568

WS(K) VM(M)
----- ----7324
79
7068
79
7192
79

CPU(s)
-----0.09
0.06
0.09

Id
-1704
6896
7988

ProcessName
----------notepad
notepad
notepad

You can see the key and an associated value to it.


The properties displayed about are present by default for a PowerShell object. You can
restrict the output to one or two properties.
3. In the PowerShell console, type the following command to view ProcessName and CPU
for instances of Notepad:
PS C:\> get-process notepad | Format-table Name,CPU -AutoSize
Name
---notepad
notepad
notepad
notepad

CPU
--0.3744024
0.0936006
0.0780005
0.0936006

4. If you want to find for how long each instance of Notepad is running, you can use a
calculated object property to find out the values.
5. In the PowerShell console, type the following command:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 179 of 361

PS C:\> get-process notepad | Format-Table ProcessName,CPU,


@{Label="TotalRunningTime";Expression={(get-date) - $_.Start
Time}} -autosize
ProcessName
----------notepad
notepad
notepad
notepad

CPU
--0.3900025
0.0936006
0.0780005
0.0936006

TotalRunningTime
---------------00:03:48.5000924
00:10:02.1069848
00:11:24.5269387
00:11:27.2600306

In the first part of the script, you can notice that to create a calculated property a hash
table is created using @{}. Later, the expression is specified to provide the value for
TotalRunningTime property.
Create a hash table and a calculated object property using the Select-Object Cmdlet.
6. In the PowerShell console, type the following command:
PS C:\> get-process

The list of all running processes on the computer appears.


7. On the next line, type the following command:
PS C:\> get-process | select-object -property ProcessName

The property, ProcessName for all processes on the computer appears.


8. In the PowerShell console, type the following command to use a calculated property:
PS C:\> get-process | select-object -property ProcessName,@{Name="Start Day";
Expression = {$_.StartTime.DayOfWeek}}

You can find on which day the processes were started.


This completes this exercise and lab.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 180 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 6: PowerShell Scripting

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 181 of 361

Lesson 6 Demonstration : Scripting


Introduction
The focus for this lesson is scripting in PowerShell. PowerShell is both a command-line shell
and a scripting language. It was designed specifically for the IT Administrator and contains a
very rich arrangement of language constructs such as variable assignments, arrays, iterations,
and flow control. This lesson describes these concepts and introduces the use of functions and
profiles.

Objectives
The objectives for this lesson are:

To define what constitutes a script and basic script elements such as:

Comments (#)

White space

Line terminators (newline, semicolon)

Script arguments

To explain how to execute a script and the security features that are applicable to running
scripts, including:

The execution policy and group policy objects

Script signing

To explain PowerShell language iteration statements such as:

Do While and Do Until

For and ForEach

While

To explain PowerShell language flow control statements, such as:

Break and continue

Return and Exit

To explain other statements that are commonly used in scripts, including:

Labeled statements

If

Switch

To describe functions and their basic features, including:

Param-blocks and Function-parameter-declaration

Argument processing

The [switch] type constraint

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 182 of 361

Named blocks (begin, process and end)

Pipelines and functions

To explain the concept of profiles in PowerShell:

Profile types

Creating and using profiles

Script libraries and dot sourcing

Prerequisites
A Windows 7 workstation logged onto with administrator credentials.

Estimated time to complete this lesson


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 183 of 361

Exercise 1: Scripting in PowerShell


Objectives
In this lesson, you will:

Create a basic PowerShell script

Describe different ways to run scripts

Set the execution policy and understand the different configurations

Describe script arguments

Scenario
A script is a collection of commands that are stored in a file with a .ps1 filename extension.
Scripts are not explicitly named within the file; instead, they take their name from the file
name.
Restricted
(default)

Permits individual commands but will not run scripts.

All Signed

Scripts can run.


Requires that all scripts be signed by a trusted publisher, including scripts that
you write on the local computer
Prompts you before running scripts from publishers that you have not yet
classified as trusted or untrusted
Risks running unsigned scripts from sources other than the Internet and
signed, but malicious, scripts
Note: Type get-help about_signing at a PowerShell command prompt to
display insyntaxion related to signing scripts.

Remote-Signed

Scripts can run.


Requires a digital signature from a trusted publisher on scripts that are
downloaded from the internet (including email and instant messaging
programs)

Unrestricted

Unsigned scripts can run.


Warns the user before running scripts from the internet

Bypass

Nothing is blocked and there are no warnings or prompts.


This execution policy is designed for configurations in which a Windows
PowerShell script is built into a larger application or for configurations in which
Windows PowerShell is the foundation for a program that has its own security
model

Undefined

There is no execution policy set in the current scope


If the execution policy in all scopes is Undefined, the effective execution
policy is Restricted, which is the default execution policy

A script contains a sequence of Unicode characters that is translated by PowerShell into a


series of tokens that can be interpreted as syntax in PowerShell.
Scripts are useful to store a series of commands that are likely to be used again in the future.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 184 of 361

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Elevated Windows PowerShell Session


1. On the Windows taskbar, right-click
.
2. Select Run As Administrator.
3. Click Yes if a User Account Control prompt appears.
The PowerShell window opens.

Task 3: Set Execution Policy


1. In the PowerShell console, type the following command to display the current execution
policies in effect on this machine:
get-executionpolicy -list

PowerShell execution policies define the conditions under which PowerShell runs scripts.
The following policies can be configured:
2. In the PowerShell console, type the following command:
set-executionpolicy unrestricted

3. Type Y to confirm the change and press Enter.


Y

This sets the execution policy for LocalMachine to unrestricted.


Execution policies can be set for:

LocalMachine

CurrentUser

Process (the current session)

A group policy object can also be used to set execution policy for computers and users.
Note: Execution policies for the local computer and current user are stored in the
registry and therefore there is no need to set execution policies in a PowerShell profile.

Task 4: Create a Basic PowerShell Script


Let us look at creating a basic PowerShell script using notepad and then add comments.
1. On the command line, type notepad.exe and press Enter to open Notepad.
Notepad.exe

2. Start your new script file by annotating the script using comments.
PowerShell treats comments as white space. White space is only used to separate tokens
in PowerShell; other than that, it is ignored for all purposes.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 185 of 361

There are three types of comments that can be used:


Single-Line-Comment
This type of comment begins with the hash character (i.e. #) and ends with one of the
line or statement termination characters i.e. new-line (enter key/Carriage return
Unicode U+000D) or semicolon (;).
Delimited-Comment
This type of comment begins with the character pair <# and ends with #> and is
useful to indicate either part of a line or multiple lines as annotation.
Requires-Comment
This is a special type of comment that can be used to specify the minimum version of
PowerShell that is required to execute a script.
The syntax is:
#requires -Version N[.n]
Where, N = major version and n = minor version. N is a required value while n is an
optional value.
A script can contain multiple requires-comments. A requires-comment must be the
first item on a line and cannot reside within a function or cmdlet.
3. Type #requires -version 3 on the first line of the file to test the requires-comment
functionality.
#requires -version 3

4. Click File > Save As, and type c:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1 in the


File name text box.
Leave the file open as we will be making changes shortly.
5. Type C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1 at the command prompt to run
the script.
The following error message appears because as you are not using PowerShell version
3.0.
C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

The script 'Lesson_6_exercise_1.ps1' cannot be run because it contained a "#requires" statement at line 1 for
Windows PowerShell version 3.0. The version required by the script does not match the currently running version
of Windows PowerShell version 2.0.
At line:1 char:15
+ .\ Lesson_6_exercise_1.ps1 <<<< + CategoryInfo
: ResourceUnavailable: (lesson_6_exercise_1:String)
[], ScriptRequiresException + FullyQualifiedErrorId : ScriptRequiresUnmatchedPSVersion

6. Change the comment in the script file from #requires -version 3 to #requires -version 2.
#requires -version 2

7. On the File menu; click Save to save the file.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 186 of 361

8. Retry the command by typing C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1 at the


command prompt.
C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

Note that the script now runs without error.


9. Type a delimited-comment starting with <# followed by some text on multiple lines and
close the delimited-comment using #>.
The script file should now resemble the following:
#requires -Version 2
<#
Author:
Date:
#>
10. On the File menu, click Save to save the file.
11. Type C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1 in the command prompt to run
the script and verify that it runs successfully.
C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

Task 5: Run PowerShell Scripts


1. Scripts can be run by typing the full path and file name as you did in the previous
procedure. That is, C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1.
2. Refer to the table below for valid and invalid ways to run a script from within the
PowerShell command shell.
Works
Fails
Full path and script file name e.g.

Double click a .ps1 file.

c:\Pshell\part1\Lesson6\ lesson_6_exercise_1.
ps1
Note: The command will fail if the path or script
file name contains any spaces. Enclosing the
command in either single (i.e. ) or double
quotes (i.e. ) will also fail. This is because the
quotes turn the command into a string.
The way to run a script file that has spaces in
its path or filename is to use single or double
quotes and prepend an ampersand (i.e. the
PowerShell Call Operator) e.g.
& c:\my documents\myscript.ps1
Typing the script file name with a prepended
dot backslash (i.e., .\) e.g.
PS
c:\users\administrator\documents> .\myscript.p
s1

Typing the script file name when the present


working directory is the directory where the
script resides e.g.
PS c:\users\administrator\documents>
myscript.ps1
Note: There is an exception to this rule:
PowerShell will run the myscript.ps1 if the
c:\users\administrator\documents folder is

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 187 of 361

listed in the Windows PATH environment


variable OR if a myscript.ps1 file is found in
ANY path that is listed in the Windows PATH
environment variable. The following command
can be used to display the content of the
Windows PATH environment variable:
$path = $env:path; $path.split(";")

3. Tips for successfully executing PowerShell script files from within the PowerShell
command shell:
A. Ensure that the execution policy allows the running of scripts.
B. Use the .\ notation to run a script that resides in the present working directory.
C. Store scripts in a folder that is listed in the Windows PATH environment variable and
run from any folder using the script name only. The following command can be used
to add a path to the Windows PATH environment variable:
$env:path = $env:path + ";c:\myscripts"

Note: This addition to the Windows PATH environment variable will be lost when
the PowerShell session is closed. The command can be added to a PowerShell Profile
(this topic is covered later in this course) if required to persist between sessions.
D. Specify the full path and filename for the script file.
E. If the path and/or the script filename contain any spaces, enclose the command with
single or double quotes and prepend with an ampersand.
4. PowerShell scripts can also be run external to the PowerShell command shell. A common
practical use for this is creating scheduled tasks that run PowerShell scripts.
5. Click Start > Run and type the following command:
powershell.exe -noexit -file c:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1 `
-executionpolicy bypass

Note: The ExecutionPolicy Bypass setting allows scripts to run regardless of whether
the current execution policy allows the running of scripts or not.

Task 6: Scripts and Accepting Arguments


Scripts can accept arguments using the $args automatic variable. $args is a
one-dimensional array that contains all arguments that are specified along with the script
name when running a script. Consider the following command as an example:
PS c:\users\administrator\documents> .\myscript.ps1 argument1 argument2 argument<n>

Arguments are separated by spaces on the command line.


Argument1, argument2 and argument<n> will be available for use in the script by indexing
into the $args automatic variable for example, $args[0] relates to argument1, $args[1] relates
to argument2.
Consider an example of this.
1. In the command prompt, type the following to open the script previously created in
Notepad:
notepad C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 188 of 361

2. Add the following lines to the Notepad file:


write-host the first argument equals: $args[0]
write-host the second argument equals: $args[1]

The file should look as follows:


#requires -Version 2
<#
Author:
Date:
#>
write-host the first argument equals: $args[0]
write-host the second argument equals: $args[1]

3. On the File menu, click Save to save the file.


4. In the command prompt, type the following command, specifying arguments:
C:\Pshell\part1\Lesson6\lesson_6_exercise_1 myarg1 myarg2

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 189 of 361

Exercise 2: Iteration Statements


Objectives
In this section, you will:

Work with the Do While and Do Until statements

Work with the For and ForEach statements

Work with the While statement

Scenario
PowerShell iteration statements provide the basic logic needed to make programmatic
decisions within a script.
PowerShell scripts use several familiar programming statements for iteration (i.e., looping
and branching).
The syntax for these statements is in the form of a script block. A script block in PowerShell
is always opened and closed with braces and contains the code to be executed if a previous
condition, defined within smooth parentheses, evaluates to true.
Iteration statements are used to loop through and execute code multiple times. Iteration is a
method to reduce the amount of code that is required to achieve a desired outcome.

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator the password, P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window opens.

Task 3: Do While and Do Until Iteration Statements


The do while iteration is similar to the foreach or for iterations. However, it continues to run
until a condition is no longer met.
The code for the loop is executed first and then the statement is evaluated. If the condition is
false, then the loop ends; otherwise the code is executed again.
Note that when using a do while iteration, you will always get one execution, even if the
condition is false to start with.
The syntax of the do while statement is as follows:
do{<code to execute>} while (<value> operator <value>)
The do until iteration is similar to the do while iteration; however, the logic for the condition
is reversed, which means that the iteration continues until a condition is true.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 190 of 361

A classic use of this iteration is in reading a file.


The iteration will continue to pass through the file, until it reaches the end.
The syntax of the do until statement is as follows:
do{<code to execute>} until (<value> operator <value>)
Let us look at an example of these two iteration statements.
1. In the command prompt, type the following to open the script previously created in
Notepad:
notepad c:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Modify the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
write-host "starting do while example..."
$i = 1
do
{
write-host iteration number $i
}
while (++$i -le 5)
write-host "starting do until example..."
$i = 1
do
{
write-host iteration number $i
}
until (++$i -gt 5)

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\Exercise_6_2a.ps1 in the


file name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\Exercise_6_2a.ps1

In the do while example, PowerShell will loop through and execute the code as long as
the value of $i is less than or equal to 5.
In the do until example, PowerShell will loop through the code until the value of $i is
greater than or equal to 5.

Task 4: For and ForEach iteration statements


The foreach iteration statement is a very powerful loop used to enumerate a collection.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 191 of 361

This is useful when you want to run the same code for a group of objects, but you do not need
to know how many objects there are in the loop. You just need to execute the same code for
each member of the collection.
The syntax of the foreach statement is as follows:
foreach (<temp variable> in <collection variable>){<code to execute>}
The for iteration statement is different from the foreach because, it can be used to loop a
certain number of passes through the code.
This is useful if only a certain number of passes is required. Another benefit of this statement
is that you have an automatic counter for the current pass of the loop.
The syntax of the for statement is as follows:
for (<initial variable> ; Boolean loop condition; counter handling){<code to execute>}
Let us look at an example of these two iteration statements.
1. In the command prompt, type the following to open the script previously created in
Notepad:
notepad C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Modify the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
write-host "starting foreach example..."
$i = 1,2,3,4,5
foreach ($t in $i)
{
write-host iteration number $t
}
write-host "starting for example..."
for ($i = 5; $i -ge 1; --$i)
{
write-host iteration number $i
}

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\lesson_6_exercise_2b.ps1 in


the file name box.
5. In the command prompt, type the following command to run the script:
C:\Pshell\part1\Lesson6\lesson_6_exercise_2b.ps1

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 192 of 361

In the foreach example, PowerShell will execute the code (i.e., write-host iteration
number $t in the example) once for each item in the variable $i.
In the for example, PowerShell will execute the code (i.e. write-host iteration number $i
in the example) as long as the variable $i is greater than or equal to 1.

Task 5: While iteration statement


The while iteration is basically the same as the do while iteration; however, the key difference
is that the condition is tested before any code is executed.
This prevents the possibility of the code or iteration running once even when the condition is
not true.
The syntax of the while iteration is as follows:
while (<value> operator <value>){<code to execute>}
Let us look at an example of this iteration statement.
1. In the command prompt, type the following to open the script previously created in
Notepad
C:\Pshell\part1\Lesson6\lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Modify the file to look like this:
write-host "starting while example..."
$i = 1
while ($i -le 5)
{
write-host iteration number $i
++$i
}

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\Exercise_6_2c.ps1 in the file
name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\Exercise_6_2c.ps1

In the while example, PowerShell will execute the code (i.e., write-host iteration
number $i;++$i in the example) as long as the variable $i is less than or equal to 5.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 193 of 361

Exercise 3: Flow control Statements


Objectives
In this lesson, we will:

Explain the Break and Continue statements

Explain the Return and Exit statements

Scenario
As the name suggests flow control statements are used to control the flow of code through a
function, loop or script.

Task1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password:
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window opens.

Task 3: Break and Continue flow control statements


The break and continue statements allow you to manage how looping constructs process.
The break statement allows you to immediately exit a loop. The break keyword allows the
code to exit from nested functions.
Consider an example of these flow control statements.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1 to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Modify the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
write-host "starting break example..."
$counter=0
while ($true)
{
if ($counter++ -ge 3)
{
break

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 194 of 361

}
$counter
}
write-host "starting continue example..."
foreach ($i in 1..10)
{
If ($i % 2)
{
Continue
}
$i
}

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\lesson_6_exercise_3a.ps1 in


the file name box.
5. In the command prompt, type the following to run the script
C:\Pshell\part1\Lesson6\lesson_6_exercise_3a.ps1

In the break example, the code would normally cause an infinite loop because the while
statement has been set to $true. However, the break keyword is called once the counter
variable is greater or equal to 3 and therefore, the loop stops.
In the continue example, the code shows a foreach loop that loops over the numbers from
1 to 10. The range operator sends a stream of numbers to the if statement, where the
modulus operator determines whether the current number is exactly divisible by 2 (i.e., an
even number). The continue operator allows the loop to re-iterate if the result is $false
(i.e., not an even number).

Task 4: Return and Exit Flow Control Statements


The return statement is used in scripts or functions to write to the pipeline and return control
back to the caller of the script or function. It is used to exit the current scope, which can be a
function, script, or script block.
The exit statement is used to exit the current script and return control to the host or a calling
script.
Consider an example of these statements.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Modify the file to look like this:
#requires -version 2
<#
Author:
Date:
#>

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 195 of 361

function Return-Example
{
write-host "starting return example..."
$i = 1
while ($i -le 5)
{
write-host iteration number $i
++$i
if ($i eq 3)
{
return $i
}
}
}
$ReturnValue = Return-Example
Write-Host "Value returned: $ReturnValue"
function Exit-Example
{
write-host "starting exit example..."
$i = 1
while ($i -le 5)
{
write-host iteration number $i
++$i
if($i -eq 3)
{
Exit $i
}
}
}
Exit-Example
Write-Host Exit code: $LastExitCode

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\lesson_6_exercise_3b.ps1 in


the file name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\lesson_6_exercise_3b.ps1

In the return statement example, PowerShell will execute the code (i.e. write-host
iteration number $i;++$i) as long as the variable $i is less than or equal to 5. However,
once the variable $i reaches 3 the loop is interrupted by the if statement condition
evaluating to true. The return statement terminates the loop and returns the value of $i at
that point.
In the exit example, PowerShell will execute the code (i.e. write-host iteration number
$i;++$i) as long as the variable $i is less than or equal to 5. However, once the variable
$i reaches 3, the loop is interrupted by the if statement condition evaluating to true. The
exit statement then terminates the script and control is handed back to the host without
executing the last line in the script. You can access $LastExitCode to view the value will
be equal to 3.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 196 of 361

Exercise 4: Other Statements


Objectives
In this lesson, we will:

Explain labeled statements

Explain the if statement

Explain the switch statement

Scenario
This section covers other statements that are commonly used in PowerShell scripting.

Log on to the VM environment


Log on to Windows 7 Enterprise client Contoso\Administrator with the password:
P@ssword

Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window opens.

Labeled statements
Statement labels allow you to explicitly refer to a statement by a name.
Consider an example of statement labels.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Change the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
:outer while ($true)
{
:inner while ($true)
{
Get-Date -displayhint time
break outer
# break from the inner & outer while statements
}
Get-Date displayhint date # this potential infinite loop is never called
}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 197 of 361

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\lesson_6_exercise_4a.ps1 in


the file name box.
5. Type the following to run the script:
C:\Pshell\part1\Lesson6\lesson_6_exercise_4a.ps1

In the labeled statement example, breaking out of an inner and an outer while loop by
using the label construct to name the first while loop is demonstrated. The nested while
loop breaks the outer loop from ever being executed (stopping the final Get-Date cmdlet,
which would have been called infinitely).

If Statement
The if statement in PowerShell is used to test for a particular condition in a Boolean statement.
The syntax of an if statement is as follows:
if (<value> operator <value>){<code to execute if true>}
elseif (<value> operator <value>){<code to execute if true>}
else{<code to execute if not true>}
Note that the elseif and else parts are optional in an if statement.
Consider an example of an if statement.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Change the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
$fooditem = Pumpkin
if ($fooditem -eq Apple)
{
"Fruit"
}
elseif ($fooditem -eq Pumpkin -or $fooditem -eq Tomato)
{
"Who knows?"
}
elseif ($fooditem -eq Carrot)
{
"Vegetable"
}
else
{
"Unknown"
}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 198 of 361

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\lesson_6_exercise_4b.ps1 in


the file name box.
5. In the command prompt, type the following to run the script
C:\Pshell\part1\Lesson6\lesson_6_exercise_4b.ps1

Switch Statement
The switch statement in PowerShell is similar to the Select Case statement in VBScript.
The switch statement is very useful when you want to test a value and run code based on a
match. The same action can be performed using a compounded if, elseif statement, but it is
more complex. In the case of a switch statement, you simply put the variable that you want to
test in the statement and then list the matches and the code to execute for each match.
Note that the default match is optional and will match anything that is not matched by any of
the other patterns.
The syntax of the switch statement is as follows:
Switch (<variable>)
{
<match 1> { <code to execute> }
<match 2> { <code to execute>}
<match n> { <code to execute> }
Default { <code to execute> }
}
Consider an example of the switch statement.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Change the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
switch ("Monday")
{
Monday {"Oh no its monday. You have to work today."}
Tuesday {"Oh no its Tuesday. You have to work today."}
Wednesday {"Its hump day, halfway there."}
Thursday {"Its TGIF eve. You have to work today"}
Friday{"Thank goodness its Friday. Almost the weekend"}
default {"It must be the weekend. No work today, you have to be happy. Its
required"}
}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 199 of 361

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\lesson_6_exercise_4c.ps1 in


the file name box.
5. In the command prompt, type the following to run the script
C:\Pshell\part1\Lesson6\lesson_6_exercise_4c.ps1

In the switch example, the value Monday is tested for a match. A match is found and
the code in the statement block is executed resulting in the text Oh no its Monday. You
have to work today. being displayed on the console. Note that the code in the statement
block for the default match would be executed if a match is not found.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 200 of 361

Exercise 5: Functions
Objectives
In this lesson, we will:

Create a basic function

Create a function with a function-parameter-declaration

Create a function with a param-block

Explain the switch type constraint

Explain named blocks and function pipelines

Scenario
Almost all programming languages employ the concept of functions, which allow code to be
encapsulated and referenced by name. This reduces the complexity of the code and makes it
more sustainable.
One important thing to note is that PowerShell functions must be declared before they can be
used in a script. In contrast to the functions used in a VBScript, PowerShell functions are
generally put at the top of the script.
To create a function, use the keyword function, followed by a name of your choice and open
a new script block with a set of curly parenthesis {}. In its most basic form, a function is a
named block of code to execute. All code within the script block will be executed each time
the function is called.
To call a function, simply state the name of the function as shown in the following example:

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

The PowerShell window opens.

Task 3: Create a basic function


1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Change the file to look like this:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 201 of 361

#requires -version 2
<#
Author:
Date:
#>
function Sort-Process
{
get-process | foreach-object {
if ($_.cpu -lt 1)
{
write-host $_.name, $_.cpu -foregroundcolor green
}
elseif ($_.cpu -gt 5)
{
write-host $_.name, $_.cpu -foregroundcolor red
}
}
}
sort-process

4. Click File, click Save As, and then type


c:\Pshell\part1\Lesson6\Lesson_6_exercise_5a.ps1 complete with the double quotes
in the file name box..
5. Run the script by typing c:\Pshell\part1\Lesson6\Lesson_6_exercise_5a.ps1 at the
command prompt.
c:\Pshell\part1\Lesson6\Lesson_6_exercise_5a.ps1

The function above is a basic function and is simply a block of code to execute, similar to
a VBScript sub-routine.

Task 4: Create a Function with function-parameter-declaration


To expand on the functionality of functions, you can build a function that requires an input
value.
To pass a value to a function, you need to define an input variable within smooth parenthesis
after the function name.
To call the function, type the function name followed by a space and the function input value.
To return a value, you can use the keyword return followed by the output variable name.
Using the return keyword forces the function to exit immediately. Alternately, you can state
the name of the output variable.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Change the file to look like this:
#requires -version 2
<#

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 202 of 361

Author:
Date:
#>
function wmiping($computername)
{
$query = "select * from win32_pingstatus where address = '" + $computername +
"'"
$wmi = get-wmiobject -query $query
write-host "pinging $computername ... "
if ($($wmi.statuscode) -eq $null)
{
$rtnvalue = $($wmi.PrimaryAddressResolutionStatus)
}
else {$rtnvalue = $($wmi.statuscode)}
return $rtnvalue
}
wmiping localhost

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\Lesson_6_exercise_5b.ps1 in


the file name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\Lesson_6_exercise_5b.ps1

The function above returns the WMI status code for a pingstatus command that is
executed against the localhost. The function is called using the function name (i.e.
wmiping) and the input value (i.e., localhost).
In the above function $computername represents a function-parameter-declaration.
Note: When a function executes, parameters are initialized to their corresponding
argument value, for example, the above function is called by its name in the script. That
is, wmiping and the $computername parameter is initialized to its corresponding
argument value i.e. localhost. If no corresponding argument value is assigned
PowerShell will use a default value, if available. A default value can be specified using
the assignment operator. Example, wmiping($computername=localhost). If there is
neither a corresponding argument value nor a default value PowerShell will use a $null
value.

Parameters can also be type constrained for example, wmiping([string]$computername).


PowerShell will convert the parameter argument to that type, if necessary.

Task 5: Create a Function with param-block


It is also possible to use a param-block. The benefit to using a param-block is that
attributes can then be specified for the expected parameters.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 203 of 361

3. Change the file to look like this:


function wmiping
{
param([Parameter(Mandatory=$true, ValueFromPipeline=$true)][string[]]$ComputerName)
$query = "select * from win32_pingstatus where address = '" + $computername + "'"
$wmi = get-wmiobject -query $query
write-host "pinging $computername ... "
if ($($wmi.statuscode) -eq $null)
{
$rtnvalue = $($wmi.PrimaryAddressResolutionStatus)
}
else {$rtnvalue = $($wmi.statuscode)}
return $rtnvalue
}
wmiping

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\Lesson_6_exercise_5c.ps1 in


the file name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\Lesson_6_exercise_5c.ps1

This function also returns the WMI status code for a pingstatus command that is executed
against the localhost. The function is again called using the function name (i.e., wmiping)
and the input value (i.e., localhost).
The $computername parameter in the function is similar to the previous example of a
function but this time we have defined attributes for the parameter. That is, Mandatory,
which is used to enforce specifying a value for the parameter and ValueFromPipeline,
which means that the parameter value can be obtained from the pipeline.

Task 6: [switch] Type Constraint Parameter


Functions also support a switch parameter. Switch parameters are Boolean, $true if present
and $false if omitted. When a switch parameter is passed, the corresponding parameter is
constrained by the [switch] type.
You can check if a switch has been passed using an If statement as follows:
if ($switchVarName) {do something!} else {do nothing}.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text.
3. Change the file to look like this:
#requires -version 2
<#
Author:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 204 of 361

Date:
#>
function multiplier ([switch]$multiply,$val1,$val2)
{
if ($multiply)
{
$val1*$val2
}
else
{
write-host The multiply switch has not been activated.
}
}
multiplier -multiply 2 4

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\Lesson_6_exercise_5d.ps1


in the file name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\Lesson_6_exercise_5d.ps1

Note that the switch can be specified anywhere in the list of parameters. For example,
multiplier -multiply 2 4 is the same as multiplier 2 -multiply 4 is also the same as
multiplier 2 4 multiply.

Task 7: Named Blocks and Pipelines


The statements within the script block of a function (i.e. within the curly braces {}) can be
contained in one large block or they can be divided into named blocks. A begin block is
executed once before the first pipeline object is sent. The process block is executed once for
each object sent on the pipeline. The end block is processed once after the last object on the
pipeline has been sent.
1. In the command prompt, type notepad
C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1 to open the script previously created
in Notepad.
notepad C:\Pshell\part1\Lesson6\Lesson_6_exercise_1.ps1

2. Remove all commands from the file, keeping only the commented text
3. Modify the file to look like this:
#requires -version 2
<#
Author:
Date:
#>
function myservicecounter
{
begin
{
$counter=0
}
process
{
if($_.status -eq "running")

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 205 of 361

{
$($_.name) `t $($_.status)";$counter++
}
}
end
{
`n$counter services running
}
}
get-service | myservicecounter

4. Click File > Save As, and type C:\Pshell\part1\Lesson6\Lesson_6_exercise_5e.ps1


in the file name box.
5. In the command prompt, type the following to run the script:
C:\Pshell\part1\Lesson6\Lesson_6_exercise_5e.ps1

Note: In this example get-service is piped to the myservicecounter function. Getservice consists of a collection of items that are made available to the function via an
enumerator that is automatically defined on entry to the function. This enumerator is
called $input.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 206 of 361

Exercise 6: Profiles
Objectives
In this lesson, we will:

Understand the different types of profiles

Understand how to view profile locations

Create a profile for the Current User

Scenario
The PowerShell host application resets every time it exits. This means that all aliases,
functions, variables and so forth that we create are lost upon exit. A PowerShell Profile can
be created to make customizations persist between PowerShell host sessions.
The ability to create a Profile is a very useful feature of PowerShell. A profile is simply a
start-up script that runs every time PowerShell starts. Each line in the script is run and
applied to each instance of PowerShell, every time PowerShell is run. (This concept is very
similar to the autoexec.bat file for those who remember the old DOS days). The profile can
hold simple lines that create new functions and aliases, or hold very complex and powerful
pieces of code.
$Profile is a special variable that can be used to retrieve the location of the current user on the
current hosts profile. $Profile always exists, however, by default the actual profile does not
exist and must be created manually. Typing $Profile displays where your personal profile
should be stored. To create the profile simply make a note of the directory structure and file
name, and create a text file with that name in the appropriate place.
There are four types of standard profiles, listed in order of precedence here:

Current User, Current Host this is the profile referenced by $profile. This profile
applies only to the current user, and is run every time PowerShell.exe is run.

Current User, All Hosts this profile applies to the current user and all PowerShell
instances, regardless of the executable host that PowerShell is hosted within.

All Users, Current Host this profile applies to all users, and is run every time
PowerShell.exe is run.

All Users, All Hosts this profile applies to all users and all PowerShell instances,
regardless of the executable host that PowerShell is hosted within.

There are also two profiles that are specific to the Integrated Scripting Environment (ISE):

ISE Current User, Current Host this is similar to the Current User, Current Host
profile. It is run instead of the normal $profile file.

ISE All Users, Current Host this is similar to the All Users, Current Host profile.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 207 of 361

Task 1: Log On to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Elevated Windows PowerShell Session


1. On the Windows taskbar, right-click
.
2. Select Run As Administrator.
3. Click Yes if a User Account Control prompt appears.
The PowerShell window opens.

Task 3: View Profile Locations


1. Type $profile | get-member -type noteproperty to view all current values of the
$profile variable.
$profile | get-member -type noteproperty

2. Type $Profile to return the Current User Current Host profile location.
$Profile

3. Type $Profile.CurrentUserAllHosts to return the Current User All Hosts profile


location.
$Profile.CurrentUserAllHosts

4. Type $Profile.AllUsersCurrentHost to return the All Users Current Host profile


location.
$Profile.AllUsersCurrentHost

5. Type $Profile.AllUsersAllHosts to return the All Users All Hosts profile location.
$Profile.AllUsersAllHosts

Task 4: Create a profile for the Current User


1. Type new-item -path $profile -type file force to create a profile.
new-item -path $profile -type file force

2. Type notepad $profile to open the newly created profile.


notepad $profile

3. Type the following in the profile file to customize the PowerShell prompt for the current
user in the current host:
function prompt{$env:computername + " " + (get-location) + "> "}

4. On the File menu, click Save to save the file.


5. Click File > Exit to close the file.
6. Open PowerShell.
Notice that the prompt has changed.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 208 of 361

Note: To start PowerShell without any profile the following command can be run:
powershell.exe noprofile

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 209 of 361

Exercise 7: Dot sourcing and Script Libraries


Objectives
In this lesson, you will:

Understand the dot sourcing concept

Learn how to create a script library

Scenario
It is a relatively common practice to create libraries of PowerShell code (such as script blocks,
functions, aliases, variables, etc.) that can be utilized on demand.
These are typically packaged into one or more library scripts that can then be dot sourced.
Dot source notation is essentially a method to make items from your script library apply to
the current scope, as opposed to only applying to a nested scope. For example a dot sourced
script that sets a variable will make that variable available to the current scope whereas the
variable would only be available to the nested script scope without dot sourcing.
The syntax to dot source a script is as follows:
. \myscript.ps1
Note there is a space between the dot and the backslash.

Task 1: Log On to VM Environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Elevated Windows PowerShell Session


1. On the Windows taskbar, right-click
.
2. Select Run As Administrator.
3. Click Yes if a User Account Control prompt appears.
The PowerShell window will open.

Task 3: Dot Source a Script file


1. In the command prompt, type notepad.exe and press Enter to open notepad.
notepad

2. Type $a=5 in the file to assign a variable.


$a=5

3. Click File > Save As, and type C:\Pshell\part1\lesson6\mydotsourcedscript.ps1 in


the file name box.
4. Click File > Save.
5. Click Save to save the file.
6. Click File > Exit to close the file.
7. Type notepad $profile to open the previously created profile.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 210 of 361

notepad $profile

8. Dot-source C:\pshell\part1\lesson6\mydotsourcedscript.ps1 in the profile file.


. C:\pshell\part1\lesson6\mydotsourcedscript.ps1

9. On the File menu, click Save to save the file.


10. Click File > Exit to close the file.
Note that there is a space between the dot and the rest of the command.
This will dot source the mydotsourcedscript script file and effectively make the variable
a available in the current scope.
11. Close and re-open PowerShell.
12. Type $a and press Enter.
$a

Note that the assigned value is returned and that the $a variable is therefore available in
the current scope.
13. Type dir variable to see a complete list of the variables that is available in the current
scope.
Dir variable:

Task 4: Remove the Dot Sourced Script file


1. Type notepad $profile to open the profile.
notepad $profile

2. Remove C:\pshell\part1\lesson6\mydotsourcedscript.ps1 from the profile file.


3. On the File menu; click Save to save the file.
4. Click File > Exit to close the file.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 211 of 361

Lesson 6 Hands-On : Scripting


Objectives
In this lab you will:

Create PowerShell scripts

Create Functions in scripts

Create PowerShell profiles

Prerequisites
The lab requires a Windows 7 client running in a domain environment.

Estimated time to complete this lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 212 of 361

Exercise 1: Create PowerShell Scripts


Task 1: Log on to the VM environment
Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Windows PowerShell Session


Open Windows PowerShell session:
On the Windows taskbar, click
. The PowerShell window opens.

Task 3: Create a basic script


1. In the command prompt, type notepad.exe to open notepad and press Enter.
Notepad.exe

2. Type the following into the file:


#requires -Version 2
<#
Author: Your name
Date: Todays date
#>
get-process | sort-object cpu descending | select-object first 5

3. Click File > Save As, and type C:\pshell\part1\lesson6\labs\top5cpu.ps1 in the file
name box.
4. In the PowerShell window, type the following to run the script:
C:\pshell\part1\lesson6\labs\top5cpu.ps1

Notice that the top 5 CPU utilizing processes are returned.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 213 of 361

Exercise 2: Create Functions in Scripts


Task 1: Log on the VM Environment
Log on to Windows 7 Enterprise client as Contoso\Administrator with the password
P@ssword

Task 2: Open Windows PowerShell Session


On the Windows taskbar, click

. The PowerShell console opens.

Task 3: Create a function in a script


1. In the command prompt, type notepad.exe and press Enter to open notepad.
Notepad.exe

2. Type the following into the file


#requires -Version 2
<#
Author: Your name
Date: Todays date
#>
function topxxcpu
{
param($number) get-process | sort-object cpu descending |
select-object first $number
}

3. Click File > Save As, and type C:\pshell\part1\lesson6\lab6\topxxcpu.ps1 in the file
name box.
4. In the command prompt, type the following to dot source the script:
. C:\pshell\part1\lesson6\labs\topxxcpu.ps1

5. In the command prompt, type the following


topxxcpu 5

Notice that the top five CPU utilizing processes are returned.
6. In the command prompt, type the following
topxxcpu 15.

Notice that the top 15 CPU utilizing processes are returned.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 214 of 361

Exercise 3: Create PowerShell Profiles


Task 1: Log on to the VM environment
Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Elevated Windows PowerShell Session


1. On the Windows taskbar, right-click
.
2. Select Run As Administrator.
3. Click Yes if a User Account Control prompt appears.
The PowerShell window opens.

Task 3: Create a Profile


1. Create a profile for all Users on all Hosts
2. Type new-item -path $profile.AllUsersAllHosts -type file force to create a profile.
new-item -path $profile.AllUsersAllHosts -type file force

3. Type notepad $profile.AllUsersAllHosts to open the newly created profile.


notepad $profile.AllUsersAllHosts

4. Type the following in the profile file to customize the PowerShell session for all users
using any PowerShell host on this computer.
write-host "Hello $env:username!`n" -foregroundcolor green
$docs=$home\documents
write-host The `$DOCS variable provides access to your documents
`n$docs`n -foregroundcolor green

located at:

5. On the File menu, click Save to save the file.


6. Click File > Exit to close the file.
7. Open PowerShell.
Notice the welcome message.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 215 of 361

Exercise 4: Explore Iteration Statements In PowerShell


Task 1: Log on to the VM environment
Log on to Windows 7 Enterprise client as Contoso\Administrator with the password,
P@ssword

Task 2: Open Elevated Windows PowerShell Session


1. On the Windows taskbar, right-click
.
2. Select Run As Administrator.
3. Click Yes if a User Account Control prompt appears.
The PowerShell window opens.

Task 3: Create Multiple Folders


1. In the command prompt, type notepad.exe and press Enter to open notepad.
Notepad.exe

2. Create a parent folder


new-item -path c:\ -name mytest -type directory

3. Create a variable named $intFolders, and ensure that it holds the value of 10. The code to
do this is shown here.
$intFolders = 10

4. Create a variable named $intPad. Do not put anything in the variable yet:
$intPad

5. Create a variable named $i, and put the number 1 in it:


$i = 1

6. Use the New-Variable cmdlet to create a variable named strPrefix. Use the value
argument of the cmdlet to assign the value of "testFolder" to the variable. Use the option
argument to change $strPrefix to a constant:
New-Variable -Name strPrefix -Value "testFolder" -Option constant

7. Open a do until statement. Include the opening curly bracket for the script block:
do {

8. Begin an if else statement. The condition to be evaluated is if the variable $i is less


than 10:
if ($i -lt 10)

9. Open the script block for the if statement. Assign the value of 0 to the variable $intPad:
{$intPad=0

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 216 of 361

10. Use the New-Item cmdlet to create a new folder. The new folder will be created in the
c:\mytest directory. The name of the new folder will be comprised of the $strPrefix
constant testFolder, the number 0 from the $intPad variable, and the number contained
in the $i variable. The code that does this is seen here.
new-item -path c:\mytest -name $strPrefix$intPad$i -type directory}

11. Add the else clause:


else

12. The else script block is the same as the if script block, except that it does not include the
0 in the name that comes from the $intPad variable. Copy the new-item line of code from
the if statement, and delete the $intPad variable from the name argument. The revised
line of code is shown here.
{new-item -path c:\mytest -name $strPrefix$i -type directory}

13. Increment the value of the $i variable by 1 by using the ++ operator:


$i++

14. Close the script block for the do clause and add the until statement. The condition that
until will evaluate is if the $i variable is equal to the value contained in the $intFolders
variable +1. The reason for adding 1 to $intFolders is so that the script will actually
create the same number of folders as is contained in the $intFolders variable. Because
this script uses a do until loop and the value of $i is incremented prior to entering the
until evaluation, then the value of $i is always 1 more than the number of folders that are
created. This code is shown here.
}until ($i -eq $intFolders+1)

15. Save your script as shown below:


C:\pshell\part1\lesson6\labs\CreateMultipleFolders.ps1

16. Run your script and confirm the results.


You should see 10 folders created in the c:\mytest directory.

Task 4: Delete Multiple Folders


1. Open the C:\pshell\part1\lesson6\labs\CreateMultipleFolders.ps1 script in Notepad or
another script editor. This script was created in the previous task.
Notepad C:\pshell\part1\lesson6\labs\CreateMultipleFolders.ps1

2. In the if else statement, the New-Item cmdlet is used twice to create folders in the
c:\mytest directory. We want to delete these folders. To do this, we need to change the
New-Item cmdlet to the Remove-Item cmdlet. The two edited script blocks are shown
here.
{$intPad=0; remove-item -path c:\mytest -name $strPrefix$intPad$i} else {remove-item
-path c:\mytest -name $strPrefix$i}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 217 of 361

3. The Remove-Item cmdlet does not have a name argument. So we need to remove this
argument but retain the code that creates the folder name. We can replace -name with a
backslash:
{$intPad=0; remove-item -path c:\mytest\$strPrefix$intPad$i} else {remove-item -path
c:\mytest\$strPrefix$i}

4. The Remove-Item cmdlet does not take a type argument. Because this argument is not
needed, it can also be removed from both Remove-Item statements. The revised script
blocks are shown here.
{$intPad=0; Remove-item -path c:\mytest\$strPrefix$intPad$i} else {Remove-item -path
c:\mytest\$strPrefix$i}

5. Save your script as shown below:


C:\pshell\part1\lesson6\labs\DeleteMultipleFolders.ps1

6. Run your script and confirm the results.


You should see that the 10 previously created folders have been deleted.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 218 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 7: Active Directory Administration
Using ADSI

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Lesson 7 Demonstration : Active Directory


Administration (ADSI)
The following section provides information and exercises for Active Directory
Administration using ADSI.

Introduction
Active Directory (AD) is Microsofts implementation of an X.500 compliant directory
service, which enables centralized access, security, and administration of network resources
using the Lightweight Directory Access Protocol (LDAP) standard.
The AD administrative tasks are commonly performed using two main GUI applications:

Active Directory Users & Computers

Active Directory Sites & Services

These applications are adequate for small addition, modification, and deletion tasks. The
applications become unmanageable when performing bulk operations in large forest
environments containing thousands or millions of objects.

Active Directory Service Interfaces (ADSI)


ADSI enables access to the directory service from different network providers, using a
variety of scripting and programming languages.
ADSI reduces the complexities of using LDAP directly to enable common administrative
tasks such as:

Adding new users or computers

Locating resources in the distributed AD environment

Objectives
After completing this lab, you will be able to:

Understand how objects are organized in AD

Create, modify, and delete AD objects using PowerShell and ADSI

Prerequisites
Windows 2008 Server and Windows 7 Client Virtual Machines

Estimated Time to Complete this Lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 220 of 361

Exercise 1: Active Directory Fundamentals


The following section provides information and tasks for Active Directory fundamentals.

Objectives
In this exercise, you will:

Learn how objects stored in AD are organized

Access objects using the ADSI type accelerator

Prerequisites
Windows PowerShell v2 must be installed on a Windows 7 client machine. A Domain
Controller running Windows 2008 must be available on the network.

Active Directory Overview


Active Directory is a directory service, which provides a centralized location to store
information in a distributed environment. The directory service stores information about
networked devices, services, and the people who use them. AD also implements services that
make this information available to users, computers, and applications. It is both:

A database storage system (directory store)

A set of services that provide a means to add, modify, delete, and locate data securely in
the directory store.

Directory Partitions
The AD database file (ntds.dit) is logically divided into a number of partitions, also known as
naming contexts. Partitioning data allows it to be replicated independently to domain
controllers in a single domain or the entire forest. There are three default AD partitions.
Partition
Name

Replication
Scope

Description

Domain

All DCs in a
Domain

Stores users, computers, groups, and other objects


specific to a single domain

Configuration

All DCs in the


Forest

Stores sites, services, and partition information for the


entire forest

Schema

All DCs in the


Forest

Stores the class and attribute definitions and rules for all
objects in the entire forest

Directory Hierarchy
Although the underlying AD storage mechanism is table based, the directory server organizes
the data into a logical hierarchy of parent and child objects.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 221 of 361

Each item in the directory is identified by a name and a two-letter prefix, known as Relative
Distinguished Name (RDN). For example, all user, group, and computer objects are prefixed
by CN.
CN=FinanceUser01

To build a tree structure, a unique path to each object is created by concatenating an objects
RDN with its parent container, until the top of the specific directory partition is reached.
This path is known as a Distinguished Name (DN) and uniquely identifies an object. DN
paths are used to connect to objects in order to create and manipulate them.
CN=FinanceUser01,OU=Finance Users,OU=Corporate Users,DC=contoso,DC=com

ADSI Providers
ADSI includes a number of service providers that allow access to different types of
directories. The following table lists service provider details.
Service
provider

Moniker

Description

LDAP

LDAP://

Namespace implementation compatible with LDAP

WinNT

WinNT://

Namespace implementation compatible with Windows


2000 or Windows NT

NDS

NDS://

Namespace implementation compatible with Novell


NetWare Directory Service (NDS)

NWCOMPAT

NWCOMPAT://

Namespace implementation compatible with Novell


NetWare 3.x

The LDAP provider fully supports AD, but cannot be used to access Windows NT or the
local Security Accounts Manager (SAM) database.
The WinNT provider can be used to access Windows NT4 domain controller directory
servers, the local SAM database on client and member server machines as well as AD
implementations, but will only support features available on Windows NT domains.
The NDS and NWCOMPAT providers allow access to the Novell NDS implementations.
For example, in order to use the LDAP provider to connect to active directory objects, prefix
the LDAP moniker (the provider name plus the two forward slashes and colon character) to
the DN of the particular object.
Note: Unlike PowerShell, all the four provider strings listed above are case sensitive.

Task 1: Bind to the Directory


1. Connect to the root of the domain partition in the contoso.com domain.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 222 of 361

Note: In LDAP terms, connecting to a DN is referred to as 'binding'.


LDAP://DC=contoso,DC=com

The above string will only appear on the screen when you type it in the PowerShell
console or include in a script.
2. To access AD, enter the [ADSI] PowerShell-type accelerator, followed by the binding
string.
PS C:\> $domain = [ADSI]LDAP://DC=contoso,DC=com
PS C:\> $domain
distinguishedName : {DC=contoso,DC=com}
Path :

3. If the computer is a domain member, you need not provide an LDAP moniker and DN,
replace it with an empty string.
By default, when the computer is a domain member, the binding string will be the root
current domain partition.
PS C:\> $domain = [ADSI]
PS C:\> $domain
distinguishedName : {DC=contoso,DC=com}
Path :

4. The [ADSI] type accelerator is just an alias to the


System.DirectoryService.DirectoryEntry .NET class, and is added to save the time to
type the fully qualified class name. Use the full name in place of the shortened alias.
PS C:\> [ADSI].fullname
PS C:\> System.DirectoryServices.DirectoryEntry
PS C:\> $domain = [System.DirectoryServices.DirectoryEntry]
PS C:\> $domain
distinguishedName : {DC=contoso,DC=com}
Path :

Task 2: Bind using Alternative Credentials


1. By default, connections to AD use the current users credentials. If you need to log on
with alternative credentials, you can create a new ADSI object, using the New-Object
Cmdlet, and specify the Moniker/DN string, username, and password.
PS C:\> $domain = New-Object
ADSI(LDAP://DC=contoso,DC=com,CONTOSO\Administrator,Password123)

2. It is not a good practice to embed passwords in scripts, you may want to use the GetCredential Cmdlet to securely store the credentials in memory, and then pass them to
the ADSI provider. The LDAP provider only accepts plaintext passwords. A workaround

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 223 of 361

is required to convert the SecureString-encoded password into plaintext, before it is


passed on to the provider.
Note: Over-the-wire credentials are never sent in plaintext.
PS C:\> $cred = Get-Credential
PS C:\> $plainTextPwd = [Runtime.InteropServices.Marshall]::PtrToStringAuto(
[Runtime.InteropServices.Marshall]::SecureStringToBSTR($cred.password))
PS C:\> $domain = New-Object
ADSI(LDAP://DC=contoso,DC=com,$cred.username,$plainTextPwd)
PS C:\> $domain
distinguishedName : {DC=contoso,DC=com}
Path :

Task 3: Bind to Specific Domain Controllers


The previous examples performed a server-less bind using the DC locator process, to find the
nearest Domain Controller in the current site automatically.
1. A specific DNS name, NETBIOS name, or IP address can be used when the requirement
is to bind to a specific Domain Controller.
[ADSI]LDAP://syddc01/DC=contoso,DC=com

2. To bind to the nearest Global Catalog (GC) server in the forest, use the GC:// moniker.
[ADSI]GC://DC=contoso,DC=com

3. Or bind to a named SYDDC01 server.


[ADSI]GC://SYDDC01/DC=contoso,DC=com

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 224 of 361

Exercise 2: Searching Active Directory


The following section provides information and tasks for search in Active Directory.

Objectives
In this exercise, you will:

Search AD for different types of objects

Search for specific objects

Modify search options

Prerequisites
Windows PowerShell v2 must be installed on a Windows 7 client machine. A Domain
Controller running Windows 2008 must be available on the network.

Task 1: Directory Searcher: Type Accelerator


In the previous exercise, you bound to a specific directory object using its DN attribute. This
exercise will help you find a single or a number of objects without knowing their DN.
AD search functionality is provided by another PowerShell type accelerator called
[ADSISEARCHER]. This is an alias to the much longer
System.DirectoryServices.DirectorySearcher .NET class name.
To use the type accelerator you must provide a DirectoryEntry object, representing the start
of the search. This is called the SearchRoot.
1. In the following example, you will create a DirectoryEntry object using the [ADSI] type
accelerator, save this reference in a variable, and pass it to the [ADSISEARCHER] type
accelerator.
$searchRoot = [ADSI]LDAP://DC=contoso,DC=com
$dirSearch = [ADSISEARCHER]$searchRoot

Alternatively, you can combine these two operations in a single line.


$dirSearch = [ADSISEARCHER][ADSI]LDAP://DC=contoso,DC=com

2. Next, use the FindAll() method to execute the search. This operation will return all
objects in the domain partition.
$dirSearch.FindAll()
Path
---LDAP://DC=contoso,DC=com
LDAP://CN=Users,DC=contoso,DC=com
systemFla...
LDAP://CN=Computers,DC=contoso,DC=com
systemFla
LDAP://OU=Domain Controllers,DC=contoso,DC=com
systemfla

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

Properties
---------{minpwdlength, dc, msds-...
{iscriticalsystemobject,
{iscriticalsystemobject,
{iscriticalsystemobject,

ITOE Educate

Page 225 of 361

LDAP://CN=System,DC=contoso,DC=com
systemfla...
LDAP://CN=LostAndFound,DC=contoso,DC=com
systemfla...
LDAP://CN=Infrastructure,DC=contoso,DC=com
systemfla...
LDAP://CN=ForeignSecurityPrincipals,DC=contoso,DC=com
systemfla...
LDAP://CN=Program Data,DC=contoso,DC=com
name...}
LDAP://CN=Microsoft,CN=Program Data,DC=contoso,DC=com
name,...}
LDAP://CN=NTDS Quotas,DC=contoso,DC=com
systemfla...
LDAP://CN=Managed Service Accounts,DC=contoso,DC=com
name...}
LDAP://CN=WinsockServices,CN=System,DC=contoso,DC=com
name...}
LDAP://CN=RpcServices,CN=System,DC=contoso,DC=com
name...}
LDAP://CN=FileLinks,CN=System,DC=contoso,DC=com
name...}
...

{iscriticalsystemobject,
{iscriticalsystemobject,
{iscriticalsystemobject,
{iscriticalsystemobject,
{objectclass, usncreated,
{objectclass, usncreated,
{iscriticalsystemobject,
{objectclass, usncreated,
{objectclass, usncreated,
{objectclass, usncreated,
{objectclass, usncreated,

Task 2: Filter Property


Directory search filtering is controlled by the Filter property of a DirectorySearcher object,
which requires a special LDAP query syntax string. Essentially, you are filtering all objects
where the attribute name specified contains a certain string.
For example, the query:
(givenName=Chris)
Translates to:
Search all objects where the givenName attribute contains the string Chris.
The following table displays the LDAP query syntax operators with examples.

Microsoft | Services

Operator

Description

Example

equal to

&

logical AND

(&(givenName=Chris)(l=Sydney))

logical OR

(|(givenName=Chris)(l=Sydney))

logical NOT

(!givenName=Chris)

Wildcard

(givenName=Chris)

(givenName=Ch*)

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 226 of 361

Note: The = operator expressions are grouped by parentheses. The & and |
operators are placed in front of the expressions wrapped in parentheses.

The default search filter is (objectClass=*). Since the wildcard operator is used, this search
filter will return all objects under the SearchRoot and all objects are derived from one or
more classes.
1. Typing the $dirSearch variable name displays the DirectorySsearcher object properties.
In this module, you will focus on the properties highlighted in bold.
$dirSearch
CacheResults
ClientTimeout
PropertyNamesOnly

: True
: -00:00:01
: False

Filter
PageSize

: (objectClass=*)
: 0

PropertiesToLoad
ReferralChasing

: {}
: External

SearchScope

: Subtree

ServerPageTimeLimit
ServerTimeLimit
SizeLimit

: -00:00:01
: -00:00:01
: 0

SearchRoot

: System.DirectoryServices.DirectoryEntry

Sort
Asynchronous
Tombstone
AttributeScopeQuery
DerefAlias
SecurityMasks
ExtendedDN

:
:
:
:
:
:
:

System.DirectoryServices.SortOption
False
False
Never
None
None

2. To return all user objects, set the Filter property to (objectCategory=user).


$dirSearch.Filter = (objectCategory=user)

3. Again, start the search by calling the DirectorySearcher objects FindAll() method. You
will see a list of all user objects, in all child containers in the domain.
$dirSearch.findAll()

4. A more complex query could include a number of expressions combined with a logical
operator and wildcard character.
The following example uses the logical AND operator (&) to return all computer objects
whose operatingSystem attribute starts with the string Windows Server.
$dirSearch.filter = (&(objectCategory=computer)(operatingSystem=Windows Server*))
$dirSearch.findAll()
Path

Microsoft | Services

Properties

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 227 of 361

---LDAP://CN=CODC1,OU=Domain Controller...
LDAP://CN=SQL2008R2,OU=SQL Servers,O...
LDAP://CN=VMMS1,OU=SCVMM Servers,OU=...
LDAP://CN=WEBSERVER,OU=Web Servers,O...
LDAP://CN=EXCHANGE2010,OU=Exchange S...
LDAP://CN=CODC2,OU=Domain Controller...
LDAP://CN=CB-LP-SVR,OU=Clients,DC=co...
LDAP://CN=COCA1,OU=Certificate Autho...
LDAP://CN=COCM1,OU=Servers,DC=contos...
LDAP://CN=CORODC1,OU=Domain Controll...

---------{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,
{primarygroupid,

iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...
iscriticalsystemobj...

Task 3: SearchScope Property


The SearchScope property controls the search behavior. The default setting is Subtree. As
demonstrated in previous examples, this property performs a recursive search from the
SearchRoot through all nested child containers.
1. The recursive search behavior can be changed by modifying the SearchScope to
"OneLevel". This setting confines the search to the SearchRoot container, in this case,
the root of the domain partition. Therefore, only Organizational Unit and Container
objects are returned.
$dirSearch.SearchScope = OneLevel
$dirSearch.FindAll()
Path
---LDAP://OU=AdminUsers,DC=contoso,DC=com
LDAP://CN=Builtin,DC=contoso,DC=com
LDAP://OU=Clients,DC=contoso,DC=com
LDAP://CN=Computers,DC=contoso,DC=com
systemflags...
LDAP://OU=Domain Controllers,DC=contoso,DC=com
systemflags...
LDAP://OU=Exchange Servers,DC=contoso,DC=com
LDAP://CN=ForeignSecurityPrincipals,DC=cont...
systemflags...
LDAP://OU=Groups,DC=contoso,DC=com
LDAP://CN=Infrastructure,DC=contoso,DC=com
systemflags...
LDAP://CN=LostAndFound,DC=contoso,DC=com
systemflags...
LDAP://CN=Managed Service Accounts,DC=conto...
...

Properties
---------{objectclass, usncreated, name...
{uascompat, objectguid, nextrid...
{objectclass, usncreated,...
{iscriticalsystemobject,
{iscriticalsystemobject,
{objectclass, usncreated...
{iscriticalsystemobject,
{objectclass, usncreated, name...
{iscriticalsystemobject,
{iscriticalsystemobject,
{objectclass, usncreated, name...

Task 4: MaxPageSize
In a large AD environment with hundreds of thousands or even millions of objects in the
forest, a DirectorySearch operation could return a huge number of results.
AD imposes a limit on the maximum number of results returned from a search. This
limitation allows you to conserve DC resources. The MaxPageSize setting at the top of the
domain partition controls this limit and is set to a default of 1,000 objects for each query.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 228 of 361

1. To overcome this problem, the DirectorySearcher object has a PageSize property,


which starts a mechanism called paging. Paging returns multiple result sets, or pages,
when a query result exceeds the MaxPageSize limit. Setting this property to any number
greater than zero will turn on the paging mechanism, which is transparent to PowerShell.
$dirSearch.PageSize = 1000

Task 5: Other Search Options


The DirectorySearcher object has many more options available to modify the search
behavior, although the Filter, SearchScope and PageSize options already covered will have
the greatest impact on search results.
The following table lists the other search options.
Name

Description

Asynchronous

Gets or sets a value that indicates if the search is performed


asynchronously.

AttributeScopeQuery

Gets or sets the LDAP display name of the DN attribute to search.


Only one attribute can be used for this type of search.

CacheResults

Gets or sets a value indicating if the result is cached on the client


computer.

ClientTimeout

Gets or sets the maximum amount of time that the client waits for the
server to return results. If the server does not respond within this time,
the search is aborted and no results are returned.

DerefAlias

Gets or sets a value indicating how the aliases of objects that are
found during a search should be resolved.

DirectorySynchronization

Gets or sets an object that represents the directory synchronization


control to use with the search.

ExtendedDN

Gets or sets a value that indicates the format of the DNs.

Filter

Gets or sets a value indicating the LDAP format filter string.

PageSize

Gets or sets a value indicating the page size in a paged search.

PropertiesToLoad

Gets a value indicating the list of properties to retrieve during the


search.

PropertyNamesOnly

Gets or sets a value indicating if the search retrieves only the names
of attributes to which values have been assigned.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 229 of 361

ReferralChasing

Gets or sets a value indicating how referrals are chased.

SearchRoot

Gets or sets a value indicating the node in the AD Domain Services


hierarchy where the search starts.

SearchScope

Gets or sets a value indicating the scope of search that is observed by


the server.

SecurityMasks

Gets or sets a value indicating which security access information for


the specified attributes should be returned by the search.

ServerPageTimeLimit

Gets or sets a value indicating the maximum amount of time the


server should search for an individual page of results. This is not the
same as the time limit for the entire search.

ServerTimeLimit

The ServerTimeLimit property gets or sets a value indicating the


maximum amount of time the server spends searching. If the time limit
is reached, only entries that are found up to that point are returned.

SizeLimit

Gets or sets a value indicating the maximum number of objects that


the server returns in a search.

Sort

Gets or sets a value indicating the property on which the results are
sorted.

Tombstone

Gets or sets a value indicating if the search should also return deleted
objects that match the search filter.

VirtualListView

Gets or sets a value indicating the virtual list view options for the
search.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 230 of 361

Exercise 3: The Directory Object Lifecycle


The following section provides information and tasks for Directory Object Lifecycle.

Objectives
In this exercise, you will:

Understand how to create new user, computer, and group objects in AD

Learn how to modify object attributes

Add users to groups

Manipulate the UserAccountControl attribute

Create and modify multiple objects in the directory

Prerequisites
Windows PowerShell v2 must be installed on a Windows 7 client machine. A Domain
Controller running Windows 2008 must be available on the network.

Task 1: Create Active Directory Objects


So far, you learnt how to connect and search for objects in AD, In addition, you can create
new objects.
To create a new object, you need the following information:

DN of the container

Class name of the object

A unique RDN (within the parent container) of the new object

Task 2: Class Name and RDN Prefix


An easy way to find object class names is to open adsiedit.msc, by clicking Start > Run >
adsiedit.msc.
Browse the Default naming context for the object type you want to create. View the Class
column and note the specified class name.
Examples of commonly used class names and RDN prefixes are listed in the table below.

Microsoft | Services

Class Name

RDN Prefix

User

CN=

Computer

CN=

Group

CN=

Organizational Unit

OU=

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 231 of 361

Figure 4:

Task 3: Create an Organizational Unit Object


Creating objects in AD involves binding to a container and using a method to create objects.
The Create() method is available only on container objects, such as the Domain Root,
Organizational Units, and Containers.
Note: The Create() method is hidden when viewing the object members using the GetMember Cmdlet.

1. To use this method to create a new Organizational Unit object at the root of the domain,
first bind to the Domain Root DN, and save a reference to it in a variable.
$objRoot = [ADSI]LDAP://DC=contoso,DC=com

2. Use the Create() method to create a new Organizational Unit object.


To do this, supply two input arguments, the class name organizationalunit and RDN
with the correct prefix for this object type (OU=). Save the resulting user object in the
$objOU variable.
$objOU = $objRoot.Create(organizationalunit,OU=Finance)

3. The new OU object is now created on the local machine. You must now save the object
to the directory. To save the object, use the SetInfo() method on the $objOU variable.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 232 of 361

$objOU.SetInfo()

4. To confirm the object was created successfully, bind to object.


[ADSI]LDAP://OU=Finance,DC=contoso,DC=com
distinguishedName : {OU=Finance,DC=contoso,DC=com}
Path
: LDAP://ou=Finance,dc=contoso,dc=com

Task 4: Create User objects


The same steps as in creating an Organizational Unit object are used for creating user objects.
In this example, you will create a new user within the Finance OU object created in the
previous steps.
1. Bind to the Finance OU object.
$objOU = [ADSI]LDAP://OU=Finance,DC=contoso,DC=com

2. Use the OUs Create() method to create the new user object.
Note: You must change the class to user and the RDN prefix to CN=.
$objUser = $objOU.Create(user,CN=FinanceUser01)

3. At this point, it is a good practice to set the samAccountName property of the new
object. Otherwise, the system will automatically create a random unique value similar to
$A91000-B3973K23LNTD. Such values are not very user-friendly log on names.
To set object attributes, use the Put() method on the new user object. Pass the name of
the attribute you want to set along with its new value.
In this example, set the user objects samAccountName attribute value to
FinanceUser01.
$objUser.Put(samaccountname,FinanceUser01)

4. Commit the new object to AD using the SetInfo() method.


$objUser.SetInfo()

Task 5: Enable User Objects


Once the user objects are created, they are disabled by default, and must be enabled before
they can be used. To enable the account, use the following steps.
1. Bind to the newly created user object.
$objUser = [ADSI]LDAP://CN=FinanceUser01,OU=Finance,DC=contoso,DC=com

2. Set the password using the user objects SetPassword() method.


$objUser.SetPassword(P@ssword1)

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 233 of 361

3. Enable the account by setting AccountDisabled property to FALSE.


$objUser.AccountDisabled = $false

4. Save the changes back to the directory.


$objUser.Setinfo()

Task 6: Manipulate the UserAccountControl Property


User accounts have different options that can be set to control security settings. In ADUC,
most options can be set in the Account tab of the user object dialog.

Figure 5:

These settings are stored as binary mask in a property called UserAccountControl on a user
object. Each bit position represents a different possible user account option that can be
checked or unchecked.
Multiple settings can be combined using PowerShells binary logical operators and are shown
in the following table.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 234 of 361

Property Flag

Value in
Hexadecimal

Value in
Decimal

SCRIPT

0x0001

ACCOUNTDISABLE

0x0002

HOMEDIR_REQUIRED

0x0008

LOCKOUT

0x0010

16

PASSWD_NOTREQD

0x0020

32

PASSWD_CANT_CHANGE

0x0040

64

ENCRYPTED_TEXT_PWD_ALLOWED

0x0080

128

TEMP_DUPLICATE_ACCOUNT

0x0100

256

NORMAL_ACCOUNT

0x0200

512

INTERDOMAIN_TRUST_ACCOUNT

0x0800

2048

WORKSTATION_TRUST_ACCOUNT

0x1000

4096

SERVER_TRUST_ACCOUNT

0x2000

8192

DONT_EXPIRE_PASSWORD

0x10000

65536

MNS_LOGON_ACCOUNT

0x20000

131072

SMARTCARD_REQUIRED

0x40000

262144

TRUSTED_FOR_DELEGATION

0x80000

524288

NOT_DELEGATED

0x100000

1048576

USE_DES_KEY_ONLY

0x200000

2097152

DONT_REQ_PREAUTH

0x400000

4194304

PASSWORD_EXPIRED

0x800000

8388608

TRUSTED_TO_AUTH_FOR_DELEGATION

0x1000000

16777216

PARTIAL_SECRETS_ACCOUNT

0x04000000

67108864

For example, to disable a user account you must perform a binary exclusive OR logical
operation (XOR) on the current value of the UserAccountControl property.
5. First, save the current value of the UserAccountControl property into a variable.
$uac = $objUser.userAccountControl.value

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 235 of 361

6. In the above table, find the bit position that controls the option you need to set. In this
case, it is 0x0002. For clarity I have saved the number into a more descriptive variable
name first.
Note: It is possible to use either the hexadecimal or decimal values.
$ACCOUNTDISABLE = 0x0002

7. Next, perform the XOR operation on the $uac variable using PowerShells bxor
operator. This enables (sets to 1) the second bit position in the UserAccountControl
bitmask.
$objUser.UserAccountControl = $uac bxor $ACCOUNTDISABLE

8. Commit the change to the directory.


$objUser.SetInfo()

It is a good practice to test if the bit position is already set before changing it, as the XOR
operator blindly flips the bit on to off and vice versa.
To do this, use the binary AND logical operator to check if the option is set.

If the result is 0, the bit position is turned off ($false).

Any positive integer indicates the bit is turned on ($true).

9. Save the value, representing the Password never expires option into a variable.
$DONT_EXPIRE_PASSWORD = 0x10000

10. Bind to the user account.


$objUser = [ADSI]LDAP://CN=FinanceUser01,OU=Finance,DC=contoso,DC=com

11. Save the UserAccountControl value into a variable.


$uac = $objUser.UserAccountControl.value

12. Use an IF statement and a band operator to determine whether the bit is already turned
on. If it is not, turn the bit position on (flip the bit) using the bxor operator.
if ($uac band $DONT_EXPIRE_PASSWORD)
{
Password never expires is already set
}
else
{
Password never expires is NOT set
Setting the password to never expire
$objUser.UserAccountControl = $uac bxor $DONT_EXPIRE_PASSWORD
$objUser.SetInfo()
}

13. To set multiple options at once, add them together and use the binary OR operator as
follows.
$SMARTCARD_REQUIRED = 0x40000

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 236 of 361

$objUser.UserAccountControl = $uac bxor ($DONT_EXPIRE_PASSWORD +


$SMARTCARD_REQUIRED)

Task 7: Modify Multivalued Attributes


Many AD object attributes hold a single value, while others can hold a list of values. These
multivalued attributes must be changed with a method other than Put().
The PutEx() method accepts an input parameter in addition to the attribute name and value
data. This parameter controls how the value is added to the multivalued attribute.
Property Name

Description

Value

Clear

Instructs the directory service to remove


all the property value(s) from the object

Update

Instructs the directory service to replace


the current value(s) with the specified
value(s)

Append

Instructs the directory service to append


the specified value(s) to the existing
values(s)

Delete

Instructs the directory service to delete


the specified value(s) from the object

Following is an example of changing multivalued attribute using PutEx() method.


1. Bind to a user object.
$objUser = [ADSI]LDAP://CN=FinanceUser01,OU=Finance Users,DC=contoso,DC=com

2. Create an array of phone numbers.


$arrPhone = 029870123456, 029870123457,029870123458

3. Update the otherHomePhone multivalued attribute using the PutEx() method.


$objUser.PutEx(2,otherHomePhone,$arrPhone)

4. Commit the changes to the directory.


$objUser.SetInfo()

Task 8: Create Group Objects


Group object creation follows the same pattern as user objects, although you have to specify
the group type before you commit the transaction to the directory.
1. Bind to the container in which you want to create the new group.
$objRoot = [ADSI]LDAP://ou=Finance,DC=contoso,DC=com

2. Again, use the Create() method to add the new group.


$objGroup = $objRoot.Create(group,CN=FinanceGlobal)

3. Set the SamAccountName attribute of the new group.


$objGroup.InvokeSet(samaccountname,FinanceGlobal)

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 237 of 361

4. Set the GroupType property of the new group object to one of its possible values, shown
in the following table.
Group Type

Hexadecimal Value

Decimal Value

Built-in Local

0x00000001

Global

0x00000002

Domain Local

0x00000004

Universal

0x00000008

Security Enabled

0x80000000

-2147483648

5. It is a good practice to assign these values to variables beforehand.


Note: It is possible to use either the hexadecimal or the decimal values.
$BUILTIN_LOCAL_GROUP
= 0x00000001
$GLOBAL_GROUP
= 0x00000002
$DOMAIN_LOCAL_GROUP
= 0x00000004
$UNIVERSAL_GROUP
= 0x00000008
$SECURITY_ENABLED_GROUP = 0x80000000

By performing a binary OR operation (-bor) on the $SECURITY_ENABLED_GROUP


variable, and any one of the other four variables you can create any of the security group
types.
Note: If you set only the GroupType to one of the first four values, a distribution group,
rather than a security group will be created.

6. Calculate the Global group binary value, and save it in the $intGlobalGroup variable.
$intGlobalGroup = $GLOBAL_GROUP bor $SECURITY_ENABLED_GROUP

7. Set the groupType attribute to the $intGlobalGroup variable using the Put() method.
$objGroup.Put(grouptype, $intGlobalGroup)

8. Finally, do not forget to commit the changes to AD.


$objGroup.SetInfo()

Task 9: Add Users to Groups


Adding users to groups is a common administrative task and can be accomplished very easily
in PowerShell.
1. Bind to a group object.
$objGroup = [ADSI]LDAP://CN=FinanceGlobal,OU=Finance Users,DC=contoso,DC=com

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 238 of 361

2. Bind to a user object.


$objUser = [ADSI]LDAP://CN=FinanceUser01,OU=Finance Users,DC=contoso,DC=com

3. Use the groups Add() method, specifying the users path property as the argument.
$objGroup.Add($objUser.Path)

4. Save the group membership change back to AD.


$objGroup.SetInfo()

Task 10: Create Computer Objects


Computer objects share most of their attributes with user objects. Therefore, apart from the
class name their creation is identical.
1. Bind to the Finance OU object.
$objOU = [ADSI]LDAP://OU=Finance,DC=contoso,DC=com

2. Use the Create() method of the OU object to create the new computer object, and save
the resulting object in the $objComputer variable.
Note: Change the RDN name to NewPC001 and the object class to computer.
$objComputer = $objOU.Create(computer,CN=NewPC001)

3. Save the new object back to AD.


$objComputer.SetInfo()

4. Computer objects are also disabled by default. To enable them, set the AccountDisabled
property to false.
$objComputer.AccountDisabled = $false

5. Commit the change to the directory.


$objComputer.SetInfo()

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 239 of 361

Lesson 7 Hands-On : Active Directory


Administration (ADSI)
The following section provides information and exercises for administering Active Directory
objects.

Objectives
This lab explores how to create, modify, and search AD objects using Windows Powershell
and ADSI.

Prerequisites
The lab requires a domain joined Windows 7 client and a Windows 2008 Domain Controller.

Estimated Time to Complete this Lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 240 of 361

Exercise 1: Create Multiple Users


The following section provides information and tasks to create multiple users.

Scenario
Most AD environments require the creation of many objects in a batch operation. You can
use many of the examples covered previously in this lesson to build a user creation script.

Objectives
The script will perform the following operations:

Take input from a .csv file to provide individual user details

Create three Organizational Units (OU), global groups, and department manager accounts

Create each batch of users listed in the userlist.csv file

Set a number of single and multivalued attributes

Add each user to a particular global group

Enable the user account and require password to be changed at first log on

Task 1: Develop a script to create AD Objects


1. Open a script editor of your choice and create a new PowerShell script file named
c:\pshell\part1\lesson7\labs\lab7-ex1.ps1.
2. Add the following lines to the text file:
A. Import the .csv file using the Import-CSV Cmdlet.
$users = Import-Csv -Path C:\pshell\part1\lesson7\labs\userlist.csv

B. Bind to the Domain Root DN.


$objDomainRoot = [ADSI]"LDAP://DC=contoso,DC=com"

3. Create variables to hold the UserAccountControl bitmask values.


$NORMAL_ACCOUNT = 0x0200
$ACCOUNTDISABLE = 0x0002

4. Add a foreach loop to iterate through the users imported from the userlist.csv file.
foreach ($user in $users)
{

5. Create OUs to hold each batch of users. Check whether the OU exists before creating it
using the [ADSI] type accelerators Exists() static method.
if (-not [adsi]::Exists("LDAP://OU=$($user.Department), DC=contoso,DC=com"))
{
$objOU = $objDomainRoot.Create("organizationalunit","OU=$($user.Department)")
$objOU.SetInfo()
}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 241 of 361

6. Create the department global groups. Check whether the group exists before creating it
using the [ADSI] type accelerators Exists() static method.
if (-not
[ADSI]::Exists("LDAP://CN=$($user.Group),OU=$($user.Department),DC=contoso,DC=com"
))
{
$objOU = [ADSI]"LDAP://OU=$($user.Department),DC=contoso,DC=com"
$objGroup = $objOU.Create("group","CN=$($user.Group)")
$objGroup.SetInfo()
}

7. Create department manager user accounts. Check whether they exists before creating
them using the [ADSI] type accelerators Exists() static method.
if (-not
[ADSI]::Exists("LDAP://CN=$($user.Manager),OU=$($user.Department),DC=contoso,DC=co
m"))
{
$objOU = [ADSI]"LDAP://OU=$($user.Department),DC=contoso,DC=com"
$objUserManager = $objOU.Create("user","CN=$($user.Manager)")
$objUserManager.SetInfo()

8. Enable the user's manager account.


$uac = $objUserManager.UserAccountControl.value
$objUserManager.UserAccountControl = $uac -bxor ($NORMAL_ACCOUNT +
$ACCOUNTDISABLE)
$objUserManager.SetInfo()
}

9. Take the first letter of current users firstname property and concatenate it with the
surname property.
$samaccountname = $user.firstName.substring(0,1) + $user.Surname
# create the user object in the correct OU for the department
$objOU = [ADSI]"LDAP://OU=$($user.Department),DC=contoso,DC=com"
$objUser = $objOU.create("user","CN=$samaccountname")
$objUser.SetInfo()

10. Set the accounts single valued attributes using the Put() method.
$objUser.Put("givenName",$user.firstName)
$objUser.Put("sn",$user.Surname)
$objUser.Put("samaccountname",$samaccountname)
$objUser.Put("displayName",$samaccountname)
$objUser.Put("UserPrincipalName","$samaccountname@contoso.com")
$objUser.Put("company","Contoso")
$objUser.Put("department",$user.Department)
$objUser.Put("homePhone","029870112233")
$objUser.Put("postOfficeBox","100")
$objUser.Put("streetAddress","1 Epping Road")
$objUser.Put("l","Sydney")
$objUser.Put("st","NSW")
$objUser.Put("postalCode","2122")
$objUser.Put("c","AU")
$objUser.Put("co","Australia")

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 242 of 361

$objUser.Put("countryCode","36")
$objUser.SetInfo()

11. Set the otherHomePhone multivalued attribute using the PutEx() method.
$arrPhone = "029870123456","029870123457","029870123458"
$objUser.PutEx(2,"otherHomePhone",$arrPhone)
$objUser.SetInfo()

12. Set the users manager attribute to the DN of the manager account.
$objUserManager =
[ADSI]"LDAP://CN=$($user.Manager),OU=$($user.Department),DC=contoso,DC=com"
$objUser.Manager += $objUserManager.distinguishedname

13. Add the user to the department global group.


$objGroup =
[ADSI]"LDAP://CN=$($user.Group),OU=$($user.Department),DC=contoso,DC=com"
$objGroup.Add($objUser.path)
$objGroup.SetInfo()

14. Enable the user account.


$uac = $objUser.UserAccountControl.value
$objUser.UserAccountControl = $uac -bxor ($NORMAL_ACCOUNT + $ACCOUNTDISABLE)
$objUser.SetInfo()
"Created User: $($objUser.distinguishedname)"
}

15. Run the script, and confirm that it worked correctly by checking ADUC, verify that the
users had been created in the LabUser OU.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 243 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 8: Administrating Active Directory
with AD Cmdlets

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 244 of 361

Lesson 8 Demonstration : Active Directory


Administration (cmdlets)
Introduction
In Windows Server 2000, Windows Server 2003, and Windows Server 2008, administrators
used a variety of command-line tools and Microsoft Management Console (MMC) snap-ins
to connect to their Active Directory domains to monitor and manage them.
The Active Directory module for Windows Powershell now provides a centralized experience
for administering your directory service installation.
With the introduction of the new Active Directory cmdlets Active Directory Domain Services
(ADDS) administrators can avoid the native .net class based complex codes.
The Active Directory module provides a host of cmdlets that comparatively reduce the length
of the scripts. These are equally capable of performing complex operations on the Active
Directory objects.

Objectives
After completing this lab, you will be able to:

Understand Active Directory administration with Windows Powershell, using the Active
Directory module and cmdlets

Pre-requisites
Windows 2008 Server and Windows 7 workstation logged onto with Domain Administrator
credentials

Estimated Time to Complete this Lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 245 of 361

Exercise 1: Using the Active Directory Module


Objectives
In this exercise, you will:

Understand the usage of the Active Directory cmdlets

Learn about the prerequisites for the Active Directory module

Open windows PowerShell and load the Active Directory module

Scenario
The Active Directory module for Windows PowerShell is a Windows PowerShell module,
named ActiveDirectory, that consolidates a group of cmdlets. These cmdlets can be used to
manage the Active Directory domains in a single, self-contained package.

Prerequisites
Windows PowerShell and the .NET Framework 3.5.1 must be installed on a Windows Server
2008 R2 or Windows 7 computer to use the Active Directory module.
You can install the Active Directory module by using any of the following methods:

By default, on a Windows Server 2008 R2 server when you install the ADDS

By default, when you make a Windows Server 2008 R2 server a Domain Controller

As part of the Remote Server Administration Tools (RSAT) feature on a Windows Server
2008 R2 server

As part of the RSAT feature on a Windows 7 computer

If you want to use the Active Directory module to manage an Active Directory domain, the
Active Directory Web Services (ADWS) service must be installed on at least one Domain
Controller in this domain.

ADWS is installed and runs by default on a Windows Server 2008 R2 Domain Controller.

For Domain Controllers running on Windows Server 2008, Windows Server 2003 R2
SP2 and Windows Server 2003 SP2 install the Active Directory Management Gateway
Service that provides a Web service interface to Active Directory domains

The Active Directory module is available in the following editions of Windows Server 2008
R2 and Windows 7:

Windows Server 2008 R2 Standard

Windows Server 2008 R2 Enterprise

Windows Server 2008 R2 Datacenter

Windows 7

Now you will load the Active Directory module for Windows PowerShell in different ways.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 246 of 361

Task 1: Log on to the VM environment


Log on to the Windows 7 client as Contoso\Administrator

Task 2: Import/Load the Active Directory module


There are different ways to open and load the Active Directory module for Windows
PowerShell.
Before you load the module on a Windows 7 Client, ensure that the Active Directory Module
for Windows PowerShell is installed using the Remote Server Administration Tools (RSAT)
1. Open Control Panel and Click on Programs and Features.
2. Click on Turn Windows Features On or Off.
3. Expand Remote Server Administration Tools> Role Administration Tools> AD DS and
AD LDS Tools.
4. Ensure that Active Directory Module for Windows PowerShell is checked.
Similarly, on Windows Server 2008 R2, you can install the Active Directory module for
PowerShell by using the Add Features Wizard.
You can follow one of the steps mentioned below to load the Active Directory module for
Windows PowerShell.
5. On the Start menu, click on Administrative Tools and then click on Active Directory
Module for Windows PowerShell.
The AD Web Service (ADWS) running on a Domain Controller is discovered and the Active
Directory module is loaded. If the service does not exist or is stopped, the Active Directory module
will fail to load. On the windows Task Bar, locate and click the
icon.
This will open the Windows PowerShell menu.
6. At the PS prompt type the following command.
get-module -ListAvailable

The output lists of all the modules can be imported into the session.
7. Now type the following command.
Import-Module Activedirectory

8. You can list all cmdlets available from this module, as follows:
Get-Command -Module "ActiveDirectory"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 247 of 361

Exercise 2: Using the Active Directory Provider


Scenario
In the previous modules, you have learned that Windows PowerShell Providers are .NET
Framework based programs that make the data in a specialized data store available, to allow
you to work as if they were mounted drives.
Administrators can use the Active Directory module provider to navigate and access data
stored in the Active Directory domains. The Active Directory module provider exposes the
Active Directory database through a hierarchical navigation system, which is very similar to
the file system. For example, while you are using the Active Directory module, you can use
the following commands to navigate through your directory:
Cd, dir, remove

Task Description
1. You can use the Active Directory module provider to map Active Directory domains to
specific provider drives. When the Active Directory module is first loaded, a default
Active Directory drive (AD:) is mounted with the root path set to RootDSE of the local
forest.
To connect to the AD: drive, run the following command:
PS c:\>cd AD:\

2. To enumerate the partitions in the forest, use dir (gci/get-childitem)


PS AD:\> Get-ChildItem
Name
---contoso
Configuration
Schema

ObjectClass
----------domainDNS
configuration
dMD

DistinguishedName
----------------DC=contoso,DC=com
CN=Configuration,DC=contoso,DC=com
CN=Schema,CN=Configuration,DC=contoso,DC=com

The Active Directory provider can be used to easily connect to any of the partitions to
query or make changes.
3. To connect to a domain, type the following command:
PS AD:\> Cd dc=contoso,dc=com
PS AD:\DC=contoso,DC=com>

4. Using dir, you can enumerate the objects in the domain, as follows:
PS AD:\DC=contoso,DC=com> dir

5. You can also connect to a child OU or container using its Distinguished Name (DN) or
Relative Distinguished Name (RDN).
The following command will set the location to the drive
AD:\OU=Test,DC=contoso,DC=com

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 248 of 361

PS AD:\DC=contoso,DC=com>cd OU=test

6. The Active Directory PSProvider can be used to create a PSDrive, which connects to the
Active Directory with specific or logged on credentials.
The following command creates a new provider drive to an Active Directory domain
using the New-PSDrive cmdlet:
New-PSDrive -PSProvider ActiveDirectory -Name Contoso `
-Root "AD:\dc=contoso,dc=com"

The other optional parameters commonly used with the cmdlet New-PSDrive are Server
and Credential.
7. In order to use the domain, server, credentials or set the search base to a specific path of
the drive, set the location (cd) to the created PSDrive.
PS c:\>set-location
PS Contoso:\>

Contoso:\

Certain generic cmdlets shown in the following table can be used with the Active Directory
provider.
Get-PSProvider

New-PSDrive

Get-PSDrive

Remove-PSDrive

Get-ChildItem

Get-Item

New-Item

Remove-Item

Move-Item

Rename-Item

Get-ItemProperty

Set-ItemProperty

Clear-ItemProperty

Get-ACL

Set-ACL

Objects can be searched, added, deleted or modified using Active Directory cmdlets, which
will be covered in the later sections of the module.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 249 of 361

Exercise 3: Cmdlets and Identity


Scenario
The Active Directory module cmdlets can be used to perform various administrative,
configuration, and diagnostic tasks in your AD DS environments. The Active Directory
module can also be used to manage the existing Active Directory user and computer accounts,
groups, organizational units (OUs), domains and forests, domain controllers, and password
policies, or to create new ones.
To list all the cmdlets that are available in the Active Directory module run the following
command
Get-Command module ActiveDirectory

The Active Directory cmdlets can be used to retrieve information, add, create, delete, move,
rename, reset, restore, search objects, set properties, enable or disable objects and features
and unlock accounts.
A group of tasks can be completed using the cmdlets to manage the following:

Account Management

Group Management

Managed Service Accounts

Organizational Units

Password Policies

Optional Features

Search\Modify Objects

Forest and Domain Management

Domain Controller

Operations Master Management

Task 1: Connecting to the local domain


1. The command to get the local ADDomain object by using your current credentials is:
PS AD:\> Get-ADDomain

Task 2: Connecting to the Global Catalog


2. To connect to a specific domain controller or port, you can use the -Server parameter.
For instance, the following will retrieve all users found in the Global Catalog on
SYDDC01:
PS AD:\> Get-ADUser Filter * -server syddc01.constoso.com:3268

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 250 of 361

Task 3: Miscellaneous Operations


3. Get all the members of the 'Schema Admins' group including the members of any nested
groups.
get-adgroupmember "Schema Admins" -recursive

4. Create a new user named 'Tkim' and set the EmployeeID and mail attributes.
New-ADUser tkim OtherAttributes @{employeeid="12345";mail="tkim@contoso.com"}

Task 4: Identity Parameter


Almost all of the Active Directory cmdlets have an identity parameter for targeting a single
Active Directory object. This parameter can also be used as the first positional argument for
quick use. For each object type, the identity parameter searches a set of attributes to find a
single match. If for some reason more than one object is found, an error will be returned.
The following table covers some of the attributes searched when you specify the identity
parameter:
Cmdlet Noun
ADComputer

ADDomain

ADDomainController

Attributes Searched for Identity

ADForest

ADGroup

Microsoft | Services

Distinguished Name
GUID (objectGUID)
Security Identifier (objectSid)
Security Accounts Manager Account Name (sAMAccountName)
Distinguished Name
GUID (objectGUID)
Security Identifier (objectSid)
DNS domain name
NetBIOS domain name
GUID (objectGUID)
IPV4Address
Global IPV6Address
DNS Host Name (dNSHostName)
Name of the server object
Distinguished Name of the NTDS Settings object
Distinguished Name of the server object that represents the
domain controller
GUID of NTDS settings object under the configuration partition
GUID of server object under the configuration partition
Distinguished Name of the computer object that represents the
domain controller
Fully qualified domain name (FQDN)
DNS host name
NetBIOS name
Distinguished Name

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 251 of 361

ADUser

ADObject
ADOrganizationalUnit

GUID (objectGUID)
Security Identifier (objectSid)
SAM User Name (sAMUserName)
Distinguished Name
GUID (objectGUID)
Security Identifier (objectSid)
SAM User Name (sAMUserName)
Distinguished Name
GUID (objectGUID)
Distinguished Name
GUID (objectGUID)

1. The following examples show how the identity parameter is used to retrieve a specific
user by using different attributes:
#match on SamAccountName
PS Contoso:\> Get-ADUser -Identity "tkim"

#SID
PS Contoso:\> Get-ADUser -Identity "S-1-5-21-1989273325-1845373034-100956730-1604"

#DistinguishedName
PS Contoso:\> Get-ADUser "CN=tkim,OU=test1,DC=contoso,DC=com"

#ObjectGUID
PS Contoso:\> Get-ADUser "fc1afcab-5c3a-400a-9d91-16431452111b"

Note: The SID and GUID used in the examples above may not match your lab
environment.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 252 of 361

Exercise 4: Searching Active Directory using Cmdlets


Scenario
The Active Directory cmdlets with the Verb Get are used to search or enumerate objects
from Active Directory.

Task Description
1. Type the following commands to list the cmdlets used to search AD object(s) of various
classes.
PS Contoso:\> gcm get-ad* | ft name
Name
---Get-ADAccountAuthorizationGroup
Get-ADAccountResultantPasswordReplicationPolicy
Get-ADComputer
Get-ADComputerServiceAccount
Get-ADDefaultDomainPasswordPolicy
Get-ADDomain
Get-ADDomainController
Get-ADDomainControllerPasswordReplicationPolicy
Get-ADDomainControllerPasswordReplicationPolicyUsage
Get-ADFineGrainedPasswordPolicy
Get-ADFineGrainedPasswordPolicySubject
Get-ADForest
Get-ADGroup
Get-ADGroupMember
Get-ADObject
Get-ADOptionalFeature
Get-ADOrganizationalUnit
Get-ADPrincipalGroupMembership
Get-ADRootDSE
Get-ADServiceAccount
Get-ADUser
Get-ADUserResultantPasswordPolicy

2. In the previous exercise, you have discussed about retrieving object information using the
Identity parameter.
For example:
Get-ADUser -Identity tkim

In order to search the Active Directory based on a pattern or criteria, using an appropriate
filter syntax becomes important. You can use the Filter or LDAPFilter parameter to
specify a query string that retrieves Active Directory objects.
In addition, certain parameters such as ResultPageSize, SearchBase or SearchScope can
be used to search the Active Directory efficiently.
3. The following command gets all the Security groups that have a Group Scope of
DomainLocal in the OU named Test1.
get-adgroup -Filter 'GroupCategory -eq "Security" -and GroupScope -eq
"DomainLocal"' SearchBase OU=Test1,dc=contoso,dc=com

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 253 of 361

4. In order to search objects in the Deleted Objects container, use the


IncludeDeletedObjects parameter as shown below.
Get-ADObject -Filter 'samaccountname -like "Vendor*"' -IncludeDeletedObjects

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 254 of 361

Exercise 5: Creating Active Directory Objects using


Cmdlets
Objectives
In this exercise, you will explore some of the Active Directory cmdlets used to create objects.

Task Description
1. In your PowerShell console, type the following commands to get the cmdlets used to
create new AD objects of various classes.
PS Contoso:\> gcm new-ad* -commandtype cmdlet | ft name
Name
---New-ADComputer
New-ADFineGrainedPasswordPolicy
New-ADGroup
New-ADObject
New-ADOrganizationalUnit
New-ADServiceAccount
New-ADUser

2. To create new users, you can use the New-ADUser cmdlet, as shown in the following
example:
PS Contoso:\> $pass = ConvertTo-SecureString "P@ssword1" -AsPlainText Force
PS Contoso:\>New-ADUser -SamAccountName "Dpark" -Name "Dan Park" `
-GivenName "Dan" -Surname "Park" `
-Department "IT" -AccountPassword $pass `
-UserPrincipalName "dpark@contoso.com"

The ConvertTo-SecureString cmdlet shown above creates a secure string which is needed
to specify the User Account password.
3. Consider another scenario where you will create a list of users from a CSV file.
The column headers in the CSV file may or may not match the Active Directory attribute
names used by New-ADUser cmdlet.
For instance, if the column headers are GivenName, Surname, Title, Department,
EmployeeId, Mail and so on, or assuming that after receiving the CSV file you
modified the column headers to match the attribute names, the following command will
create bulk users.
PS Contoso:\>Import-CSV c:\pshell\part1\lesson8\userlist.csv | New-ADUser

4. If the column headers do not match the attribute names, the cmdlet Select-Object can be
used to calculate the properties as shown in the following example.
PS Contoso:\>Import-CSV c:\pshell\part1\lesson8\userlist.csv | Select `
@{Name="GivenName";Expression={$_."First Name"}}, `
@{Name="Surname";Expression={$_."Last Name"}}, `

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 255 of 361

@{Name="Title";Expression={$_."Job Title"}}, `
@{Name="Department";Expression={$_.Section}}, `
@{Name="Employeeid";Expression={$_."Employee ID"}} | New-ADUser

5. Now explore the cmdlet New-ADGroup to create a new group named 'Managers' in the
container 'CN=Users,DC=Contoso,DC=Com' and set the GroupCategory, DisplayName,
GroupScope, and Description properties on the new object.
C:\PS>New-ADGroup -Name "Managers" -SamAccountName Managers -GroupCategory
Security -GroupScope Global -DisplayName "Managers" -Path
"CN=Users,DC=Contoso,DC=Com" -Description "Members of this group are floor
Managers

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 256 of 361

Exercise 6: Modifying Objects using Cmdlets


Scenario
Now that you are familiar with cmdlets used to search and create objects, you can explore
some of the Active Directory cmdlets used to modify existing AD objects.

Task Description
1. In your PowerShell console, type the following command to get the cmdlets used to
modify AD objects of various classes.
PS Contoso:\> gcm set-ad* -commandtype cmdlet | ft name
Name
---Set-ADAccountControl
Set-ADAccountExpiration
Set-ADAccountPassword
Set-ADComputer
Set-ADDefaultDomainPasswordPolicy
Set-ADDomain
Set-ADDomainMode
Set-ADFineGrainedPasswordPolicy
Set-ADForest
Set-ADForestMode
Set-ADGroup
Set-ADObject
Set-ADOrganizationalUnit
Set-ADServiceAccount
Set-ADUser

2. A simple example shown below updates the company and department attributes on a
single target identity.
Set-ADUser Dpark -Company Contoso -Department 'Sales'

Bulk Modifications
You might encounter scenarios with many users in an environment, who do not have a
UserPrincialName (UPN) configured. In these scenarios, you can use Get-ADUser to search
for users without a UPN and pipe the results to Set-ADUser to modify the user accounts.
3. If you simply want to set the user account to be the sAMAccountName with the domain
suffix, you can use a command similar to the one shown below:
Get-ADUser -filter {UserPrincipalname -notlike "*"} | ForEach-Object {Set-ADuser Identity $_ -UserPrincipalName "$($_.sAMAccountName)@contoso.com"}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 257 of 361

Exercise 7: PowerShell Credential Objects and Using


Alternative Credentials for Cmdlets
Scenario
The Active Directory cmdlets have the Credential parameter to use alternate credentials to
perform a task in the current session. The default credentials are the credentials of the
currently logged-on user, unless the cmdlet is run with the account associated with an Active
Directory PowerShell provider drive.
To specify this parameter, you can type a user name, such as "Contoso\User01" or you can
specify a PSCredential object.

Task Description
1. If you specify a user name for this parameter, the cmdlet prompts for a password.
Get-ADComputer filter samaccountname notlike syd* searchbase OU=Domain
Controllers,DC=contoso,dc=com -credential contoso\administrator

2. You can also create a PSCredential object by using a script or by using the GetCredential cmdlet. You can then set the Credential parameter to the PSCredential object.
3. The following example shows how to create credentials.
$DomainCreds = Get-Credential "Contoso\administrator"

4. The following shows how to set the Credential parameter to these credentials.
Get-ADuser Identity tkim -Credential $DomainCreds

5. Often, when using alternate credentials or specifying specific server connection settings,
it can become tedious to specify these parameters for every cmdlet being used. In
addition, each time you specify these parameters, a new session is set up, which has some
performance costs associated with it. A better approach is to use the Active Directory
PSProvider to create a PSDrive, which connects to the Active Directory.
New-PSDrive -PSProvider ActiveDirectory -Name Contoso -Root `
"AD:\dc=contoso,dc=com" credential $DomainCreds

The syntax shown above creates a PSdrive named Contoso connected with the credentials
specified in the DomainCreds variable.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 258 of 361

Lesson 8 Hands-On : Active Directory


Administration (cmdlets)
Objectives
The objective for this lab is to explore creating, modifying and searching Active directory
objects using the Windows PowerShell Active Directory Cmdlets.

Prerequisites
The lab requires a windows 7 client running in a domain environment.

Estimated time to complete this lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 259 of 361

Exercise 1: Creating Multiple Users in an


Organizational Unit
Objectives
In this exercise, you will:

Create an Organizational Unit (OU)

Create nine temporary user accounts in the OU using concatenation

Specify certain attribute values for the users from a text file, populate those on the
General, Address and Profile tabs

Scenario
The AD administrator of Contoso Limited receives a request for creating lab users for their
development work. The users belong to the same physical location, hence a common address.
In addition to the name, surname, UPN and e-mail address attributes, the users would also
have a home directory and roaming profile stored on the respective shares on the server
Syddc01.
The administrator will have to automate the user creation using the Active Directory modules
for Windows PowerShell.

Duration
10 minutes

Task 1: Develop a script that will create AD Objects


1. Log on to the VM environment:
Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword
2. Open Notepad or another script editor
3. Open the file c:\pshell\part1\lesson8\lab8\address.txt.
This file contains the address details that will be used for the test users.
4. Create a new file in the ISE or notepad and save it as c:\pshell\part1\lesson8\labs\lab8ex1.ps1
5. For the first line of the file enter the following code
$error.clear()

This will ensure that only errors related to the script are reported.
6. Type the following line to load the Active Directory module.
Import-module activedirectory

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 260 of 361

7. In order to create an OU named LabUsers in which the users will be created, type the
following line
New-ADOrganizationalUnit -Name LabUsers -Path "DC=CONTOSO,DC=COM

8. Type the following code for the next line of the script
$aryText = Get-Content -Path "c:\pshell\part1\lesson8\labs\address.txt"

This will load the address details from the file that will be used for the user accounts.
9. On the next line, type the following code to create a variable for the username prefix.
$Username = "LabUser"

10. On the next line, type the following code to create the variable for the max user count.
$intUsers = 9

11. On the next line, type the following code to create a variable for the user path.
$userpath = "OU=LabUsers,DC=contoso,DC=com"

12. On the next line, type the following code on the next line to start the for loop.
for ($i=1; $i -le $intUsers; $i++)

13. On the next line, type the following code to open the script block.
{

14. On the next line, type the following code to create each user account with the attributes to
be populated in the General, Address and Profile tabs.
new-aduser -name $username$i -samaccountname $username$i -path $userpath `
-displayname "$username$i" -givenname "$username$i" -surname "surname" `
-Initials $i -Description $($aryText[0]) `
-UserPrincipalName "$username$i@contoso.com" `
-EmailAddress "$username$i.surname@contoso.com" -StreetAddress "$($aryText[1])" `
-city "$($aryText[2])" -state "$($aryText[3])" -PostalCode "$($aryText[4])" `
-OfficePhone "02-$i$i$i$i-$i$i$i$i" `
-ProfilePath "\\syddc01\users\$username$i" -HomeDrive "h" `
-HomeDirectory "\\syddc01\userdata\$username$i"

15. On the next line, type the following code to close out the For loop.
}

16. Now save the script.


17. Launch Windows PowerShell session.
18. In the PowerShell console, type the following to execute the script.
c:\pshell\part1\lesson8\labs\lab8-ex1.ps1

The script should execute and create the users and populate the user properties.
19. In ADUC, check for the users in the LabUsers OU.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 261 of 361

20. Check one of the users property tabs. You will see that the user properties have been
populated.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 262 of 361

Exercise 2: Modifying AD objects via Cmdlets


Objectives
In this exercise, you will:

Modify the attributes of existing users using the Set-ADuser cmdlet

Perform a bulk deletion of the lab users

Scenario
The Contoso management requires redeployment of first five lab users to a different
development project. From now on, those lab users will be located at a different office.
The AD administrator requires to automate the change of address details using the Active
Directory modules for Windows PowerShell.

Duration
10 minutes

Task 1: Develop a script to modify AD Objects


1. Log on to the VM environment:
Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword
2. Open Notepad or another script editor.
3. Open the file c:\pshell\part1\lesson8\labs\NewAddress.txt.
This file contains the new address details of the relocated lab users.
4. Create a new file in the ISE or notepad and save it as c:\pshell\part1\lesson8\labs\lab8ex2.ps1
5. For the first line of the file, enter the following code.
$error.clear()

This will ensure that only errors related to the script are reported.
6. Type the following line to load the Active Directory module.
Import-module activedirectory

7. Type the following code for the next line of the script.
$aryText = Get-Content -Path "c:\pshell\part1\lesson8\labs\NewAddress.txt"

This will load the address details from the file that will be used to change or update the
address details of the user accounts.
8. On the next line, type the following code to create a variable for the username prefix.
$Username = "LabUser"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 263 of 361

9. On the next line, type the following code to create the variable for the max user count to
be modified.
$intUsers = 5

10. On the next line, type the following code on the next line to start the For loop.
for ($i=1; $i -le $intUsers; $i++)

11. On the next line, type the following code to open the script block.
{

12. On the next line, type the following code to modify the target user accounts address
details.
set-aduser -identity $username$i -StreetAddress "$($aryText[0])" `
-city "$($aryText[1])" -state "$($aryText[2])" -PostalCode "$($aryText[3])"

13. On the next line, type the following code to close out the For loop.
}

14. Now save the script.


15. Launch Windows PowerShell session.
16. In the PowerShell console, type the following to execute the script.
c:\pshell\part1\lesson8\labs\lab8-ex2.ps1

The script should execute and modify the users address details.
In ADUC, refresh the view and check for the users in the OU.
17. Check one of the users Address property tab. You will see that the user properties have
been modified.
18. Open the script c:\pshell\part1\lesson8\lab8\lab8-ex2.ps1 and save it as
c:\pshell\part1\lesson8\lab8\lab8-ex2a.ps1
19. Now delete the following lines of code from the script.
set-aduser -identity $username$i -StreetAddress "$($aryText[0])" `
-city "$($aryText[1])" -state "$($aryText[2])" -PostalCode "$($aryText[3])"

20. Now type the following code between the { and } lines
Remove-aduser -Identity "$username$i"

21. Save the script.


22. The new script will now delete the lab user accounts from Active Directory.
23. In the PowerShell console, type the following to execute the script.
c:\pshell\part1\lesson8\lab8\lab8-ex2a.ps1

The script should execute and delete the users.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 264 of 361

Exercise 3: Searching AD objects via Cmdlets


Objectives
In this exercise, you will:

Search Active Directory based on a filter syntax

Use the cmdlet Get-AdUser

Scenario
During an Active Directory disaster recovery exercise, Contoso DR management team
expressed the requirement to have a script that would populate all the objects that have been
deleted in the last seven days.
The AD administrator will need to write the script that will search the Deleted Objects
container and list the objects deleted in the last seven days.

Duration
10 minutes

Task 1: Find AD Objects deleted in the past 7 days


1. Log on to the VM environment:
Log on to on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword
2. Open Notepad or another script editor.
3. Create a file named c:\pshell\part1\lesson8\labs\lab8-ex3.ps1 in notepad or the
PowerShell ISE and save it.
4. For the first line of the file, after the comment section (#), enter the following code.
$error.clear()

This will ensure that only errors related to the script are reported.
5. Type the following line to load the Active Directory module.
Import-module activedirectory

6. Type the following code for the next line of the script to specify the CSV file path to
which the output will be exported.
$csvpath = "c:\pshell\part1\lesson8\labs\deletedobjects.csv"

7. On the next line, type the following code to create a variable to store the datetime
(current date 7 days) object.
$deletedindays = (get-date).adddays("-7")

8. On the next line, type the following code to create the variable for the search filter string.
$searchfilter= 'isdeleted -eq $true -and whenchanged -gt $deletedindays'

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 265 of 361

The filter above would search for objects that have their IsDeleted attribute set to True
and the whenchanged attribute is within the last 7 days.
9. On the next line, type the following code to search AD according to the filter string
(including the Deleted Objects container) and store the result in the designated CSV file.
Get-ADObject -Filter $searchfilter -IncludeDeletedObjects | select
name,objectclass | export-csv -Path $csvpath -notypeinformation

10. Now save the script.


11. Launch Windows PowerShell session.
12. In the PowerShell console, type the following to execute the script.
c:\pshell\part1\lesson8\labs\lab8-ex3.ps1

The script should execute and search the deleted objects.


13. Open the CSV file "c:\pshell\part1\lesson8\lab8\deletedobjects.csv" and check for the
desired results.
notepad "c:\pshell\part1\lesson8\labs\deletedobjects.csv"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 266 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 9: Windows Management
Instrumentation

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Lesson 9 Demonstration : Windows Management


Instrumentation (WMI)
Introduction
In this section, you will cover the core concepts of Windows Management Instrumentation,
better known as WMI. These concepts include working with classes, gathering data both
locally and remotely as well as real-world applications.

Objectives
After completing this lab, you will be able to:

Describe the core WMI concepts in Windows

Leverage the Get-WMIObject cmdlet to access WMI from within PowerShell

Review some of the most commonly used WMI classes

Discover gathering data remotely using Get-WMIObject

Filter and sort returned WMI data

Provide best practices when leveraging WMI in scripting

Prerequisites

A Windows 7 workstation logged in with administrator credentials

A Windows 2008 server logged in with administrator credentials

Estimated time to complete this lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 268 of 361

Exercise 1: Introduction to WMI


Objectives
In this exercise, you will:

Learn the fundamentals of WMI.

Identify the basic WMI components and related tools in Windows.

Understand basic information related to the service.

Scenario
WMI is an integral part of Windows infrastructure and is installed by default. In this scenario,
we will explore the WMI Management console and underlying services.

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as:

Username: Contoso\Administrator

Password: P@ssword

Task 2: Open Windows PowerShell


On the Windows taskbar, click

The PowerShell console opens.

Concepts of Instrumentation
Instrumentation is the act of making data available through an avenue of communication. In
programming terms, that translates to being able to gather trace information, performance
data or verbose error logging.
Instrumentation can be fully understood in a more familiar context. Consider an automobile.
When we want to know the status of a vehicle's component, we rely on instrumentation to do
it. Since we cannot speak directly to the car, we have to use an infrastructure that allows
communication. The gauge on the dashboard interacts with various sensors throughout the
vehicle and translates data, allowing you to see various conditions (such as current speed and
fuel level).
Hardware (Engine)

Data Translation (Gauge)

Raw data

Object

User readable

Instrumentation in Windows is very similar. It allows drivers and components to output data
that can then be used by users or other processes. This effectively allows us to speak to
deeper layers of the OS and hardware.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 269 of 361

WMI Organization
WMI is built around the concepts of Classes, Instances and Namespaces.
A Class is essentially anything WMI can manage. It is a template for an underlying object
and describes its function. All objects of each Class follow the same basic layout; however,
the actual data they contain is unique to that object.
Common Class Types
Hardware Classes
Software Classes
Operating System Classes
Performance Counter Classes

Describe Hardware events/data (static)


Describe Software events/data (dynamic)
Describe OS specific information
Describe Performance data (Perfmon) counters

An Instance represents the objects within each class. Each object follows a template
described by the parent Class in which it resides.
Namespaces are logical groupings of Classes.

Namespace

WMI Class

Object Instance

WMI Class

Object Instance

Object Instance

Object Instance

All content for WMI resides in a database known as a Repository. The default Repository
location in Windows is:
%Systemroot%\WBEM\Repository

Task 3: Work with WMI: Control Console


1. Click Start > Run, and type the following command:
WMIMGMT.MSC

2. Explore the WMI tabs for information.


From this pane, you can gather basic information such as location of WMI repository on
disk, WMI revision and Security information.

Task 4: Inspect the WMI Services


1. Using SC.EXE from the Command line to gather service information, you can see several
key pieces of data on the WMI management service:
C:\> sc.exe qc winmgmt
SERVICE_NAME: winmgmt
TYPE

Microsoft | Services

: 20

WIN32_SHARE_PROCESS

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 270 of 361

START_TYPE
ERROR_CONTROL
BINARY_PATH_NAME
LOAD_ORDER_GROUP
TAG
DISPLAY_NAME
DEPENDENCIES
SERVICE_START_NAME

:
:
:
:
:
:
:
:

2
AUTO_START
0
IGNORE
C:\Windows\system32\svchost.exe -k netsvcs
0
Windows Management Instrumentation
RPCSS
localSystem

C:\> sc.exe query winmgmt


SERVICE_NAME: winmgmt
TYPE
STATE

: 20 WIN32_SHARE_PROCESS
: 4 RUNNING
(STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
: 0 (0x0)
: 0 (0x0)
: 0x0
: 0x0

WIN32_EXIT_CODE
SERVICE_EXIT_CODE
CHECKPOINT
WAIT_HINT

2. Using PowerShells Get-Service Cmdlet to query the service information:


PS> get-service winmgmt | format-list *

Name
:
RequiredServices
:
CanPauseAndContinue : True
CanShutdown
:
CanStop
:
DisplayName
: Windows
DependentServices
:
MachineName
: .
ServiceName
:
ServicesDependedOn
:
ServiceHandle
:
Status
:
ServiceType
:
Site
:
Container
:

winmgmt
{RPCSS}
True
True
Management Instrumentation
{WinTarget, vmms, vhdsvc, SharedAccess...}
winmgmt
{RPCSS}
SafeServiceHandle
Running
Win32ShareProcess

The PowerShell output varies slightly from the SC.EXE returned information.

Task 5: List WMI Namespaces


1. In the PowerShell console, type the following command to list the WMI namespaces.
Get-wmiobject class __namespace namespace root | select name

You will now see a list of the available namespaces in the WMI repository from the root.
This, however, is only the top layer of the available namespaces. There are subnamespaces available but the command above does not display them.
2. In the PowerShell console, run the script recurse-namespaces.ps1

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 271 of 361

This script will display all the namespaces and sub-namespaces available for the current
machine.
For almost all purposes, you will use the root\cimv2 namespace.
function searchns($ns)
{
write-host $ns -foregroundcolor white
$colns = get-wmiobject -namespace $ns -class "__namespace"
if ($colns -ne $null)
{
foreach ($i in $colns)
{
$subns = $i.__namespace+"\"+$i.name
searchns($subns)
}
}
}
Write-host "The Following are all the namespaces and sub namespaces in `n WMI on
the local machine" -foregroundcolor green
searchns("root")

This script will now display the full list of available WMI namespaces and sub-name
spaces. You will notice that there are many available namespaces and sub-namespaces.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 272 of 361

Exercise 2: WMI Classes and Queries


Now you will explore the types of data that can be returned from WMI via PowerShell. The
primary and most common cmdlet for accessing WMI data is the Get-WmiObject
commandlet. From this point forward, you will be primarily working with this commandlet
and the subset of returned data. However, before looking into the cmdlet you need to list the
available classes for a given namespace.

Task 1: List Available Classes


1. From the PowerShell console, type the following to list the available classes.
Get-wmiobject -list

You will now see a list of the available WMI classes for the root\cimv2 namespace.
Root\cimv2 is the default namespace used by WMI. This default namespace is used by
the get-wmiobject Cmdlet if you do not specify it.
2. Type the following to display only the names of the WMI classes.
Get-wmiobject list | select name

Task 2: Understand WMI Metadata


You will notice that in addition to the normal WMI classes, you also have metadata classes.
Metadata is information about WMI. This could be:

Data about namespaces or classes

Other WMI information such as configuration

Additional information about a WMI class such as its superclass

The WMI metadata is visible as anything that starts with a double underscore or __. This
makes it easy to filter as you can look for anything that does not start with __.
1. Type the following in the PowerShell console to filter out the metadata classes.
Get-wmiobject list | where-object {$_.name like win32_*}

As you can see from the output, this displays all the properties of the class without the
metadata. You can use the range wildcard to out the metadata for all WMI classes and
other queries.

Task 3: Understand the Get-WMIObject Cmdlet


The get-wmiobject cmdlet is the cmdlet that allows us easy access to WMI data from within
PowerShell. This cmdlet allows for very simple access to local WMI data, as well as more
complex access such as remoting and WMI queries. This cmdlet has been available from
PowerShell version 1 and at that time was one of the few cmdlets that supported remote data
collection. In PowerShell 2.0, the ability to use WMI as a background job as well as the
ability to use WMI events.
2. From within the PowerShell console, inspect what the get-wmiobject cmdtlet can do
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 273 of 361

Get-Help Get-WmiObject -examples

1. From the examples, it appears that the get-wmiobject cmdlet can return a wide variety
of data from WMI objects. Now, perform a basic query on a Logical Disk Class.
Get-WmiObject Class Win32_LogicalDisk

DeviceID
DriveType
ProviderName
FreeSpace
Size
VolumeName

:
:
:
:
:
:

C:
3

DeviceID
DriveType
ProviderName
FreeSpace
Size
VolumeName

: E:
: 5
:
:
:
:

87575044096
497958252544
Windows 7

You will notice that in this query, the namespace is not specified. PowerShell will use:

The default WMI scripting namespace defined via the WMI control console, or

What is defined in the registry key HKLM:\Software\Microsoft\WBEM\Scripting Default


namespace

From this simple query, you can gather some useful information related to the current diskrelated hardware on the machine. The first entry lists the DeviceID C: and a DriveType of 3.
There are other fields designating metrics such as Total Size and Volume Name.
The second entry had a DeviceID of E: and has a different DriveType of 5. Note that there
is no data for other fields.
DriveType Reference
#
Type:
-------------------------------------------------------------------------------------------------------------1
No Root Directory
2
Removable Disk
3
Local Disk
4
Network Drive
5
Compact Disc
6
RAM Disk

From this quick data collection, you can infer that C is a Hard Disk approximately
500Gigabytes in size, while E is a CD/DVD unit with no media loaded.
For further details, you can use the WMI SDK file reference that is on the desktop of the
workstation. The file is WMISKD_School.chm. You can find details for every WMI class in
the MSDN documentation website.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 274 of 361

Now, expanding on that concept, look at the Win32_Bios class and see what data can be
gathered about the machine:
PS> Get-WmiObject Class Win32_Bios

SMBIOSBIOSVersion
Manufacturer
Name
SerialNumber
Version

:
:
:
:
:

090004
American Megatrends Inc.
BIOS Date: 03/19/09 22:51:32 Ver: 09.00.04
0654-6116-5806-0058-2049-6801-11
VRTUAL - 3000919

This returned only a small portion of the available data held in the Win32_Bios class. To get
the full output, pipe the contents to a Format-List.
Get-WmiObject class Win32_Bios | fl *

You will see here that the WMI metadata is also returned. To filter this metadata out, you can
use the a-z range wildcard.
Type the following to filter out the metadata and display only the properties for the class.
Get-wmiobject class win32_bios | format-list [a-g]*

In some cases, other cmdlets use WMI to return data (although often filtered in some fashion).
Now, compare the output from Get-Service to Get-WmiObject against the Netlogon
service:
Get-wmiobject Win32_Service| ?{$_.name eq netlogon} | fl *
Name
Status
ExitCode
DesktopInteract
ErrorControl
PathName
ServiceType
StartMode
AcceptPause
AcceptStop
Caption
CheckPoint
CreationClassName

:
:
:
:
:
:
:
:
:
:
:
:
:

Netlogon
OK
1077
False
Normal
C:\Windows\system32\lsass.exe
Share Process
Manual
False
False
Netlogon
0
Win32_Service

Description
: Maintains a secure channel between this computer and the
domain controller for authenticating users and services. If this service is stopped,
the computer may not authenticate users and records. If this service is disabled,any
services that explicitly depend on it will fail to start.
DisplayName
InstallDate
ProcessId
ServiceSpecificExitCode
Started
StartName
State
SystemCreationClassName

Microsoft | Services

:
:
:
:
:
:
:
:

Netlogon
0
0
False
LocalSystem
Stopped
Win32_ComputerSystem

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 275 of 361

SystemName
TagId
WaitHint
Scope
Path
Options
ClassPath
Properties
SystemProperties
Qualifiers

:
:
:
:
:
:
:
:
:
:

CONTOSO
0
0
System.Management.ManagementScope
\\CONTOSO\root\cimv2:Win32_Service.Name="Netlogon"
System.Management.ObjectGetOptions
\\CONTOSO\root\cimv2:Win32_Service
{AcceptPause, AcceptStop, Caption, CheckPoint...}
{__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}
{dynamic, Locale, provider, UUID}

get-service netlogon | fl *

Name
RequiredServices
CanPauseAndContinue
CanShutdown
CanStop
DisplayName
DependentServices
MachineName
ServiceName
ServicesDependedOn
ServiceHandle
Status
ServiceType
Site
Container

:
:
:
:
:
:
:
:
:
:
:
:
:
:
:

Netlogon
{LanmanWorkstation}
False
False
False
netlogon
{}
.
Netlogon
{LanmanWorkstation}
SafeServiceHandle
Stopped
Win32ShareProcess

Both methods of access return data related to services, but the WMI object directly is far
more verbose.
To find out what other Classes are available to us, use the Get-WmiObject cmdlet to return
an entire list (this may take a minute to enumerate depending on machine speed).
PS:> Get-WmiObject -list

As you can see, there are more than a thousand default/base classes available for a wide
range of components. Additional classes are often included for different product lines such as
SharePoint, IIS and Exchange.
If you need information on methods, this code snippet will query WMI and extract all the
available methods for all classes.
PS:> Get-WmiObject -List * |
Where-Object{$_.Methods -ne $Null} |
Select-Object -ExpandProperty Methods |
Sort-Object Origin,Name |
Select-Object Origin,Name -Unique

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 276 of 361

Task 4: Understand Get-wmiobject Parameters


The get-WMIObject cmdlet has additional parameters that are very useful since they can be
used to significantly change the behavior of the cmdlet . Some of these make it clear as to
what the cmdlet is operating on, while others can change the type of query used by the cmdlet
or what credentials or impersonation level the query is run as. Not all parameters will be
covered, but some of the important ones that you should be aware of will be.
-namespace Parameter
The first parameter you will look at is the -namespace. This optional parameter is used to
specify the namespace to query. In WMI, you always have to query a namespace; however,
for most purposes the default namespace of root\cimv2 is used. In fact, if you do not specify
a namespace this is the namespace that will be used. You can test this with the following
examples:

1. In the PowerShell console, type the following command and press Enter.
Get-wmiobject win32_computersystem

You will see that the information for win32_computer system is displayed.
2. In the PowerShell console, type the following command and press Enter.
Get-wmiobject namespace root\cimv2 win32_computersystem

You will see that the information for win32_computer system is displayed. This is the
same as the information displayed when not specifying the namespace.
This information is important for two main reasons.

Although most of the information you will be working with will come from
root\cimv2, there are times that you may need to get information from other
namespaces. An example of this is the System Center Configuration Manager client
agent. The Client agent has its own WMI namespace, which can be used to trigger
client agent actions such as check for advertisements or perform software or
hardware inventory.

The other reason you should know about the -namespace parameter is because the
default namespace on the machine might change. While this is rare, if you are writing
scripts that rely on the default value and never check it or explicitly specify it, your
code could have errors. It is good practice to always specify the namespace in scripts,
to ensure you are addressing the correct namespace.

-class Parameter
The class parameter is a required parameter and the default parameter. This means that the
first value passed to the cmdlet will, by default, be assigned to the class parameter. The class
is the WMI class that you wish to obtain information from. For example, the following are
the same command:
Get-wmiobject win32_process
Get-wmiobject class win32_process

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 277 of 361

Similarly, always specifying the namespace parameter in scripts, is also a good practice to
specify the class parameter. This does not always apply to interactive console use, as it is
important to minimize the amount of typing done in the PowerShell console. However, the
parameter should always be used in scripts. So, for example, the following should be used in
a PowerShell script.
Get-wmiobject namespace root\cimv2 class win32_process

-list Parameter
The -list parameter is used to list the available classes for a given namespace. If the
namespace is not specified then the default name space of root\cimv2 is used.
-computer Parameter
The -computer parameter is used to specify the computer to be queried. The parameter is
optional and the local computer is used unless specified otherwise. In the WMI query
language (WQL) that will be covered shortly, the local computer is referred to as a . You can
specify the parameter and use the . to ensure you are working against the local computer or
you can specify the NetBIOS, FQDN or even IP address of a remote machine to query.

For example,
Get-wmiobject computer syddc01 namespace root\cimv2 class win32_share

-credential Parameter
Like several other cmdlets , the -credential parameter is used to allow the get-wmiobject
cmdlet to be run as another account. This parameter requires a PowerShell credential object.
If specified with the username, it will prompt for the password. This is typically used when
also specifying the -computername parameter.

For example,
$creds = get-credential
Get-wmiobject computer syddc01 namespace root\cimv2 class win32_share credential
$creds

-EnableAllPrivileges Parameter
The -EnableAllPrivileges parameter is used to enable all privileges for the current user. This
is sometimes needed, as some special WMI privileges are used with some methods that are
not normally granted by default. The best example of this is the shutdown computer right. If
the -EnableAllPrivileges parameter is not specified, calling the method will fail.

Task 5: Understand Queries using WQL


WMI contains its own query language, called WMI query language and WQL for short. This
language allows complex SQL-like queries to be run against a class or collection of classes to
return specific data. However, WQL is not a complete T-SQL language and is instead a
limited subset of T-SQL. As a result, WQL only supports fairly simple queries and limited
keywords. The more complex programing statements of T-SQL are not available (such as if

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 278 of 361

statements). If you reference the WMI SDK and look for the topic on WQL, you will find the
full list of keywords and operators available for WQL.
The basic structure of a WQL query is very similar to SQL.
<Select> | properties | <from> | class | <where>| filter criteria
The first two sections, the select and from are mandatory. The where section is optional.

The select Section


The select section can be used to retrieve only properties of interest. This is done by
specifying the names of these properties. If multiple properties are required, they can be
separated by a comma. This has an impact on the amount of data retrieved and transmitted
(for remote queries).
It is a good practice to retrieve only information of interest. It is acceptable to use select * if
you want all the properties of a class or instance. It is also useful when testing a query or if
you do not know what properties are available. However, for the verified queries, only the
information of interest should be retrieved.
For example,
Get-WmiObject Query Select name, startmode, state from win32_service | format -list
*

You will notice that even though only the name, startmode and state properties have been
selected, using the format-list Cmdlet displays these properties as well as the WMI metadata
as the __ classes. This is unavoidable, as the WMI service will always return the metadata.
This can be dealt with in two ways.

It can be filtered from display using format-list [a-z]*. However, the data is still there.

It can be discarded by using the select-object Cmdlet and specifying the properties of
interest.

The from Section


The from section is the simplest section of the query. This is the name of the WMI class to
query.

The where Section.


The where section is used to:

Select a WMI instance of interest, or

Check if a WMI instance matches a criteria

This is similar to the where-object Cmdlet. However, it is much more powerful as the WMI
service performs the filtering.
In our example above, using a Get-WMIObject against the Service class returns all objects.
You can then filter them using the Where-Object Cmdlet.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 279 of 361

Get-wmiobject Win32_Service| where-object {$_.name eq netlogon}This is effective but


rather inefficient if you are concerned with very specific data. Now, using the WQL structure,
you can issue the same query with more specific expected results:
Get-WmiObject Query Select * from win32_service where name=netlogon

Note the use of the double quotes inside the single quote string. This is due to the way the
Cmdlet and the query works. The reason for this is that the query needs to be a string in
PowerShell, while the query is actually a command for the WMI service. As such, the value
of netlogon needs to be passed to the WMI service as a string. The use of the double quotes
inside the single quotes allows for a string inside a string. It is also possible to use this in the
opposite way and have single quotes inside a double quote string. The latter is more common
as it allows for variables to be used and expanded inside the query string.
ExitCode
Name
ProcessId
StartMode
State
Status

:
:
:
:
:
:

0
Netlogon
604
Auto
Running
OK

Now, you are selectively targeting just the Netlogon service as part of the query. Only this
object is returned rather than a collection of all objects.
For a local query, the results will be very similar. However, there is an execution advantage
in getting the WMI query to perform the filtering. This is because the WMI service will be
performing the filtering. For a remote query, this is very important as the amount of data
retrieved from the WMI service and then transmitted over the network is very different. The
execution time is also affected. This is also very important in scripts, as you will often be
retrieving WMI information from multiple machines.
A major difference to be aware of when using WQL is the operators used in the where
section. The operators used here are WQL operators and not PowerShell operators. The
following are the WQL operators and their descriptions:
Operator

Description

Equal to

<

Less than

>

Greater than

<=

Less than or equal to

>=

Greater than or equal to

!= or <>

Not equal to

Is

Is

Is not

Is not

Like

Wildcard match

There are two other things you need to be aware of with WQL, that are different from the
PowerShell language:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 280 of 361

Logic keywords in the where section

WQL wildcards

The WQL wildcards are below. These are used only in the where section.
Character

Description

[]

Any one character within the specified range ([a=c])


or a set ([abcdefg])

Any one character not within the specified range


([^a=c]) or a set ([^abcdefg])

Any string of zero or more characters. Similar to *

_ or (underscore)

Any single character. Any literal underscore used in


the query string must be escaped by placing it
inside [] or square brackets

The logic keywords available for use in the WQL language are the words AND and OR as
well round brackets (). The normal algebraic logic rules apply here, with both the use of the
keywords and the brackets.

Using the -filter Parameter


Get-WMIObject also supports the action of Filtering directly within the Cmdlet itself.
Instead of using a WQL Select statement, you can use the -filter parameter to access a
property directly. This is a shortcut directly to the where section of the query and uses the
WQL operators (not the PowerShell operators). In the example above, you retrieved service
information on the Netlogon service. Now perform the same action, this time using the -filter
parameter:
gwmi win32_service -filter 'name = "netlogon"'

ExitCode
Name
ProcessId
StartMode
State
Status

:
:
:
:
:
:

0
Netlogon
604
Auto
Running
OK

We get the same data set returned in either scenario. Using the -filter criteria may be
advantageous when only a small subset of data is desired (specific property) while the WQL
query is more robust.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 281 of 361

Exercise 3: WMI Remoting and Method Execution


Task 1: WMI Remoting
The power of WMI really comes into play with gathering data from remote sources. In
PowerShell the Get-WmiObject cmdlet is the main source of data retrieval. In the previous
exercise, it was used to gather data from a single machine.
The Get-WmiObject cmdlet supports the -ComputerName parameter. This means that,
natively, the cmdlet is equipped to gather data remotely. Any WMI query that can be run
locally can also be run remotely by adding the -ComputerName switch.
Now you will use the Win32_Bios class to demonstrate the remote abilities:
Get-WmiObject Class Win32_Bios

SMBIOSBIOSVersion
Manufacturer
Name
SerialNumber

:
:
:
:

090006
American Megatrends Inc.
BIOS Date: 05/23/12 17:15:53 Ver: 09.00.06
5841-1807-8159-8121-4504-5660-30

Version
: VRTUAL - 5001223Use the same command, but now executed against a
machine named syddc01
Get-WmiObject -Computername "syddc01" -Class Win32_Bios

SMBIOSBIOSVersion
Manufacturer
Name
SerialNumber

:
:
:
:

090006
American Megatrends Inc.
BIOS Date: 05/23/12 17:15:53 Ver: 09.00.06
5661-8327-5168-3547-0914-4161-08

Version
: VRTUAL - 5001223The data returned from the local (Virtual) machine
differs from the data retrieved from the remote machine (in this case a different virtual
machine with a different serial number).

Task 2: Method Execution


Like all other objects available for use in PowerShell, WMI object also contains both
properties and methods. These methods allow you to make configuration changes to system
objects such as services or network cards, or schedule events such as a chkdsk.
To expose the methods available for a WMI class, you can simply use the get-member
cmdlet just like any other PowerShell object.
1. In the PowerShell console, type the following:
get-wmiobject namespace root\cimv2 class win32_service | get-member `
membertype method | select name

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 282 of 361

TypeName: System.Management.ManagementObject#root\cimv2\Win32_Service
Name
---Change
ChangeStartMode
Delete
GetSecurityDescriptor
InterrogateService
PauseService
ResumeService
SetSecurityDescriptor
StartService
StopService
UserControlService

MemberType Definition
---------- ---------Method
Change(System.String DisplayName, System.Str...
Method
ChangeStartMode(System.String StartMode)
Method
Delete()
Method
GetSecurityDescriptor()
Method
InterrogateService()
Method
PauseService()
Method
ResumeService()
Method
SetSecurityDescriptor(System.Management.Mana...
Method
StartService()
Method
StopService()
Method
UserControlService(System.Byte ControlCode)

TypeName: System.Management.ManagementObject#root\cimv2\Win32_TerminalService
Name
---Change
ChangeStartMode
Delete
GetSecurityDescriptor
InterrogateService
PauseService
ResumeService
SetSecurityDescriptor
StartService
StopService
UserControlService

MemberType Definition
---------- ---------Method
Change(System.String DisplayName, System.Str...
Method
ChangeStartMode(System.String StartMode)
Method
Delete()
Method
GetSecurityDescriptor()
Method
InterrogateService()
Method
PauseService()
Method
ResumeService()
Method
SetSecurityDescriptor(System.Management.Mana...
Method
StartService()
Method
StopService()
Method
UserControlService(System.Byte ControlCode)

Note that the output has been modified for display purposes.
As you can see from the output, using get-member you can easily display the methods
available for a WMI class.
To execute one of these methods, there are a few things you need to remember. First, for
multiple instance classes, you need to isolate the results to a single instance to execute the
method on.
Second, you need to know how the method works. For each WMI class, and even each
WMI method, these can be very different. Just like a .NET class, you will need to
reference each WMI class and each method to know how they work. This is again in the
WMI SDK. In the example above, you used the win32_service class, which contains an
instance for each service on the system. For example, to be able to use the stopservice
method, you need to target just one service. For this example, you will use the BITS
server.
2. In the PowerShell console, type the following:
$bits = get-wmiobject namespace root\cimv2 class win32_service filter `
name=bits

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 283 of 361

The code above assigns the BITS service object to the variable $bits, which allows you
to execute the method using the dot notation. You can do this as a single line using
brackets. However, keeping the variable creates a repeatable reference for the object.
The next step is to execute the method.
3. In the PowerShell console, type the following:
$bits.stopservice()

__GENUS
__CLASS
__SUPERCLASS
__DYNASTY
__RELPATH
__PROPERTY_COUNT
__DERIVATION
__SERVER
__NAMESPACE
__PATH
ReturnValue

:
:
:
:
:
:
:
:
:
:
:

2
__PARAMETERS
__PARAMETERS
1
{}

You will notice that after executing the method, you will get return information from
WMI. The most important of this information is the return code. The return code is also
method and class specific so these need to be referenced. However, as a general rule, a
return code of zero is a success and any other return code is an error of some description.
For the StopService method, all the following are possible return codes.
Return
Code

Description

Return
Code

Description

Success

13

Service dependency failure

Not supported

14

Service disabled

Access denied

15

Service logon failed

Dependent services
running

16

Service marked for deletion

Invalid service control

17

Service no thread

Service cannot accept


control

18

Status circular dependency

Service not active

19

Status duplicate name

Service request timeout

20

Status - invalid name

Unknown failure

21

Status - invalid parameter

Path not found

22

Status - invalid service account

10

Service already stopped

23

Status - service exists

11

Service database locked

24

Service already paused

12

Service dependency
deleted

As you can see, the return codes can contain a lot of useful status information.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 284 of 361

Now, in this circumstance, you have changed the status of the bits service from running
to stopped. Check out the results
In the PowerShell console, type the following:
$bits
ExitCode
Name
ProcessId
StartMode
State
Status

:
:
:
:
:
:

0
BITS
1052
Auto
Running
OK

Clearly, the output appears incorrect? The output using the variable reference shows that
the service is still running and this is after you have executed the stopservice method
and got a return code of 0 for success. The issue here is that the data in the $bit variable
is not dynamic. Therefore, because WMI is a query-based system the information stored
in the $bit reference is the status at the time of assignment to the variable. If you want to
look at the current status, you need to run the query and assignment again.
4. Type the following in the PowerShell console to execute the query and assignment again.
$bits = get-wmiobject namespace root\cimv2 class win32_service filter
name=bits

5. Now type the following to display the current status.


$bits
ExitCode
Name
ProcessId
StartMode
State
Status

:
:
:
:
:
:

0
BITS
1052
Auto
Stopped
OK

The stopservice method does not require any parameters to be passed when using the
method call. However, there are other methods that require parameters to be passed.
Now, look at another common method that you might use when managing services with
WMI. This is the changestartmode method. This method allows you to change the start
mode of the server. There are several types of start modes that can be set. By specifying
this, the startmode will be changed accordingly.
To use the parameter in PowerShell, like all other methods, use a string with the value
from the table. An advantage of this WMI class is that the return codes for this method
are the same as the return codes for the stopservice method.
Below are the parameters for the changestartmode method:
Value

Meaning

Boot

Device driver started by the operating system loader. This value


is valid only for driver services

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 285 of 361

System

Device driver started by the operating system initialization


process. This value is valid only for driver services

Automatic

Service to be started automatically by the service control


manager during system startup

Manual

Service to be started by the service control manager when a


process calls the StartService method

Disabled

Service that can no longer be started.

Now, change the start mode of the bits service from Auto to manual.
6. In the PowerShell console type the following:
$bits.changestartmode(manual)
__GENUS
__CLASS
__SUPERCLASS
__DYNASTY
__RELPATH
__PROPERTY_COUNT
__DERIVATION
__SERVER
__NAMESPACE
__PATH
ReturnValue

:
:
:
:
:
:
:
:
:
:
:

2
__PARAMETERS
__PARAMETERS
1
{}

To get the current status of the service after the change you can either re-execute the
query, or execute a new one.
7. In the PowerShell console, type the following to check the current status.
Get-wmiobject namespace root\cimv2 class win32_service filter name=bits

ExitCode
Name
ProcessId
StartMode
State
Status

Microsoft | Services

:
:
:
:
:
:

0
BITS
1052
Manual
Stopped
OK

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 286 of 361

Exercise 4: Common WMI Classes Used


One challenge with WMI is finding where the information you need is stored. This is partly
due to the size of the WMI class library. There are more than 900 classes on a typical
machine, each containing multiple properties. This makes it very easy to become
overwhelmed unless you know of some of the key common classes that contain most of the
information you may need (as a system administrator).
Once you are familiar with WMI, you might find that of the over 900 classes there are only a
dozen or so that you use regularly. This section describes some of the common classes and
their contents, and demonstrates using some of them. Some of these you have already looked
at in this lesson and some of these will be new.
Class name

Description

Win32_bios

Contains information from the computer bios.


Information such as machine model and serial
number can be obtained

win32_computersystem

Contains some hardware and operating system


information about a system. This is good general
class for system information

win32_diskdrive

Contains information about physical drives on a


system as presented to windows.

win32_logicaldisk

Contains information about logical drives on a


system as presented to windows. This class can
also be used to schedule or cancel a scheduled
chkdsk scan at boot.

Win32_NetworkAdapterConfiguration

Contains information about the network adapters


on the system. This class can also be used to set
network configurations such as IP addresses and
DNS servers.

win32_operatingsystem

Contains detailed information about the current


operating system

win32_pingstatus

This class performs a WMI ping on a remote


target.

win32_printer

Contains information about printers on the local


system

Win32_PrinterDriver

Contains information about the current printer


drivers installed on a system

Win32_Printershare

Contains information about any shared printers on


a system

Win32_PrinterConfiguration

Contains information about printer configuration on


a system

win32_printjob

Contains information about print jobs on a system

win32_process

Contains information about processes on a


system. It can also be used to start and stop
processes

win32_processor

Contains information about the CPU of a system

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 287 of 361

win32_product

Contains information about software that has been


installed via the Windows Installer service. Note
that this class is not supported on Windows Server
2003, Windows XP or Windows 2000.

Win32_QuickFixEngineering

Contains information about the current applied


hotfixes for a system

win32_service

Contains information about the services on a


system. can also be used to change the state and
configuration of the services

win32_share

Contains information about the current network


shares on a system. can also be used to create
network shares on a system

win32_systemenclosure

Contains information about a physical system


enclosure. This is mostly useful for server system.

win32_timezone

Contains time zone information for a system. This


includes the time zone offset from UTC and if
daylight saving is in effect.

win32_userprofile

Contains information about the user profiles on a


system

win32_utctime

Contains information about the current time,


broken down into hours, minutes, seconds, day,
month and year.

As you can see from the classes in the table, a large amount of system information is covered
by these classes. While these will not exclusively be the WMI classes you will use, they will
contain most of the information that you need as a systems administrator.
Now you will look as some of the classes that have not been dealt with already.

Task 1: Understand Win32_pingstatus


The win32_Pingstatus class is a special WMI class. This class is used to perform a WMI
ping on a target by way of a WMI query.
This is very useful in scripts for two main reasons.
It a very quick to perform a WMI ping when the target responds. This makes writing scripts
that ping multiple machines run quite fast when the majority of targets respond.
The second use of this is to test whether or not a WMI connection can be established before
running a WMI query on a remote machine. This is a good practice when using WMI on a
remote target. This allows you to test the target first with a WMI ping and, if it succeeds,
proceed to the WMI query, or handle errors if not. The means that it is a great candidate to
build into a function library and dot source in most scripts.
The class works by using a WQL query of the class and specifying the target in the where
section of the query. This can be the NetBIOS name, FQDN or IP address of the machine to
ping.
For example,
Get-wmiobject query select * from win32_pingstatus where address="syddc01"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 288 of 361

Below is an example of building the WMI ping into a function. The examples also include a
function to look up the result code from the query and display the description for the return
code.
8. Open the ISE and enter the following code:
#functions
Function wmiping($strcomputername)
{
$strQuery = "select * from win32_pingstatus where address = '" +
$strcomputername + "'"
$wmi = Get-WmiObject -Query $strQuery
Write-Host "Pinging $strcomputername ... "
if ($($wmi.statuscode) -eq $null)
{
$rtnvalue = $($wmi.PrimaryAddressResolutionStatus)
}
else {$rtnvalue = $($wmi.statuscode)}
return $rtnvalue
}
Function pingerror($errcode)
{
switch ($errcode)
{
11001 {$errdetails
11002 {$errdetails
11003 {$errdetails
11004 {$errdetails
11005 {$errdetails
11006 {$errdetails
11007 {$errdetails
11008 {$errdetails
11009 {$errdetails
11010 {$errdetails
11011 {$errdetails
11012 {$errdetails
11013 {$errdetails
11014 {$errdetails
11015 {$errdetails
11016 {$errdetails
11017 {$errdetails
11018 {$errdetails
11032 {$errdetails
11050 {$errdetails

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

"Buffer Too Small"}


"Destination Net Unreachable"}
"Destination Host Unreachable"}
"Destination Protocol Unreachable"}
"Destination Port Unreachable"}
"No Resources"}
"Bad Option"}
"Hardware Error"}
"Packet Too Big"}
"Request Timed Out"}
"Bad Request"}
"Bad Route"}
"TimeToLive Expired Transit"}
"TimeToLive Expired Reassembly"}
"Parameter Problem"}
"Source Quench"}
"Option Too Big"}
"Bad Destination"}
"Negotiating IPSEC"}
"General Failure"}

default {$errdetails = "unknown error"}


}
return $errdetails
}
# Main code
cls
do
{
Write-Host "This script will ping an IP address or machine name"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 289 of 361

$strcomp = Read-Host "Please enter an IP address or computer name to ping"


$rtn = wmiping $strcomp
if ($rtn -eq 0)
{"success"}
else
{ $rtn = pingerror $rtn "error : " + $rtn}
} until ($invalue -eq "q")

9. Save the file as WMIPingScript.ps1.


10. Run the script and enter a machine or IP address to ping when prompted.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 290 of 361

Lesson 9 Hands-On : Windows Management


Instrumentation (WMI)
Introduction
In this section, you will cover the core concepts of Windows Management Instrumentation,
better known as WMI. These concepts include working with classes, gathering data both
locally and remotely as well as real-world applications.

Objectives
After completing this lab, you will be able to:

Describe the core WMI concepts in Windows

Leverage the Get-WMIObject cmdlet to access WMI from within PowerShell

Review some of the most commonly used WMI classes

Discover gathering data remotely using Get-WMIObject

Filter and sort returned WMI data

Provide best practices when leveraging WMI in scripting

Prerequisites

A Windows 7 workstation logged in with administrator credentials

A Windows 2008 server logged in with administrator credentials

Estimated time to complete this lab


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 291 of 361

Exercise 1: WMI Classes and Queries


Objectives
In this exercise, you will:

Use the most common WMI cmdlet in Powershell: get-wmiobject

Enumerate some basic information with it

Try different syntaxes for querying

Discover some useful, frequently used classes

Generate some errors to see how they appear

Estimated time to complete this lab


10 minutes

Scenario
Now that you have seen how to access WMI in Windows, you can use PowerShell 1.0 or 2.0
to get information from it.
At this time, your focus will be on getting only local information.

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client:

Username: Contoso\Administrator

Password: P@ssword

Task 2: Open Windows PowerShell Session


Click the

icon on the windows task bar

The PowerShell window will open.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 292 of 361

Task 3: Examine a WMI Class


1. In the PowerShell console, run the following command::
get-wmiobject

-Class Win32_quickfixengineering

This is the basic Cmdlet to enumerate the contents of a WMI Class. You provide only the
Class Name; all the other parameters have good defaults.
This WMI class, win32_quickfixengineering, will display the current applied hotfixes
on a system.
2. In the PowerShell console, run the following to reformat the data.
Get-wmiobject class win32_quickfixengineering | format-table hotfixid,
description, installedby, installedon

You will now see that the source column is no longer displayed and the KB number is
now the first column displayed.
3. Type the following into the PowerShell console to export the list of hotfixes to a text file.
Get-wmiobject class win32_quickfixengineering | select-object hotfixid,
description, installedby, installedon > hotfixes.txt

Now examine the text file produced. You will see that it contains the list of the hotfixes.
Question A:

notepad .\hotfixes.txtWhy was select-object used instead of formattable in the example above?

Answer: Select object was used as it discards any additional data aside from the
specified properties. Format-table on the other hand is for formatting the information
displayed in the PowerShell console.
4. Type the following in the PowerShell console to export the list of hotfixes to a .CSV file.
Get-wmiobject class win32_quickfixengineering | export-csv hotfixes.csv `
-notypeinformation

Now examine the .CSV file in notepad.


notepad .\hotfixes.csv

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 293 of 361

Exercise 2: Basic Filtering


Objectives
In this exercise, you will:

Work with the network adapter configuration WMI class

Filter the class to find the active network adapter

Estimated time to complete this lab


10 minutes

Scenario
One very useful WMI class is the win32_networkadapterconfiguration class. This class
however needs to be filtered to get the useful information out. This is common with many
WMI classes.

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client:

User name; Contoso\Administrator

Password:P@ssword

Task 2: Open Windows PowerShell Session


Click the

icon on the windows task bar

The PowerShell window will open.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 294 of 361

Task 3: List network adapters on the system


1. In the PowerShell console, type the following command to list the network adapters on
the local system:
Get-wmiobject namespace root\cimv2 class win32_networkadapterconfiguration

You will now see a long list of network adapters available on the system. Some of these
include the RAS adapters, the WAN mini port and other such adapters. For most
purposes, you are not concerned or interested in these adapters. However if you were
there is lots of information available for these.
Most of the time you will be interested in the adapter that contains a valid IP address as
this will be the active NIC that is being used. To look at this adapter, you need to filter
out the other adapters.
Question B:

Based on the information displayed, what is the property that offers


the easiest way to filter network adapters?

Answer : From what is displayed, the IP address will be the easiest way to filter the
network adapters.
2. In the PowerShell console, type the following command to filter the network adapters:
Get-wmiobject namespace root\cimv2 class win32_networkadapterconfiguration |
where-object {$_.ipaddress ne $null}

This will filter the network adapters down to just the NICs that have an IP address.
However, you are aware that using where-object is not the most effective way of
filtering WMI instances.
The IPAddress property is a little tricky. This property is an array property, since a NIC
can have multiple IP Addresses, although this is not very common. Therefore, querying
this property for a NULL value will not work. Instead, look at all the properties available
for the network adapter.
3. In the PowerShell console, type the following to display all the information for the
network adapter with an IP address.
Get-wmiobject namespace root\cimv2 class win32_networkadapterconfiguration |
where-object {$_.ipaddress ne $null} | format-list *

You will see all the properties for the network adapter displayed. Examine this
information and look at the properties. One of these properties will let you know if the
network adapter has an IP address.
Question C:

What is the property that lets you know if the network adapter has an
IP Address?

Answer: The property is IPEnabled.


Now that you have found the property IPEnabled, you can use it in a WMI query or
filter to get just the NIC or NICs with IP Addresses.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 295 of 361

4. In the PowerShell console, run the following command to filter using a WMI query.
Get-wmiobject query select * from win32_networkadapterconfiguration where
ipenabled = true

The NIC with an IP address configured will now be displayed.


5. Now type the following to display the same information using the -filter parameter.
Get-wmiobject namespace root\cimv2 class win32_networkadapterconfiguration `
filter ipenabled = true

You will see the information displayed is the same using either method. It is a matter of
preference as to which you will use.
6. In the PowerShell console, run the following command to display all the information for
the WMI class instance.
Get-wmiobject namespace root\cimv2 class win32_networkadapterconfiguration `
filter ipenabled = true | format-list [a-z]*

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 296 of 361

Exercise 3: WMI Method Execution


Objectives
In this exercise, you will:

Get information from remote machines, using WMI

Use the WMI ping to test connectivity

Execute WMI methods to make configuration changes

Estimated time to complete this lab


15 minutes

Scenario
When working with WMI classes and information it is possible to not only obtain
information, but also to make changes using WMI methods. In this exercise you will execute
some methods on the win32_networkadapterconfiguration class.

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username: Contoso\Administrator

Password: P@ssword

Task 2: Open Windows PowerShell Session


Click the

icon on the windows task bar

The PowerShell window will open.

Task 3: Test DNS and Gateway Values


Following on from the previous example of looking at the network adapters that have an IP
address, the next step is to verify the DNS settings and gateway to be valid. To do this, you
will first get the values, and then use WMI ping to test the values.
There is a much easier way to test the network addresses through WMI, which is testconnection. However, as this is a WMI lesson you will use WMI instead.
1. In the PowerShell console, run the following command to list the network adapters on the
local system that have a valid IP address:
Get-wmiobject query select * from win32_networkadapterconfiguration where
ipenabled = true | format-list *

The DNS servers and gateway properties will now be in the list of properties. You will
now use WMI ping to verify that these values are correct.
2. Run the following command to test the first DNS server:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 297 of 361

Get-wmiobject query select * from win32_pingstatus where address=<DNS SERVER>


| ft ipv4address, statuscode -autosize

Where <DNS SERVER> is the IP address of the DNS server from the first query in the
DNSServerSearchOrder property.
Question A:

Did the query return a success or a failure?

Answer: The first DNS server will ping successfully.


3. Repeat the command from step 2 but replace it with a second DNS server.
Get-wmiobject query select * from win32_pingstatus where address=<DNS SERVER>
| ft ipv4address, statuscode -autosize

Where <DNS SERVER> is the IP address of another DNS server from the first query in
the DNSServerSearchOrder property.
Question B:

Question? Did the query return a success or a failure?

Answer: The second DNS server will not ping successfully, as it is not online in the
lab environment.
Now you will test the gateway to verify that it is correct.
4. Type the following command to verify the default gateway address.
Get-wmiobject query select * from win32_pingstatus where address=<DEFAULT
GATEWAY> | ft ipv4address, statuscode -autosize

Where <DEFAULT GATEWAY> is the IP address of the default gateway from the first
query.
Question C:

Question? Did the query return a success or a failure?

Answer: The default gateway server will ping successfully.


Now that the DNS servers and default gateway addresses have been verified, you can now
use WMI methods to modify these values.

Task 4: Set DNS Server Search Order


To set the DNS server search order, the win32_networkadapterconfiguration class includes
a method called setDNSServerSearchOrder which allows you to both define the DNS
servers and also to set the search order.
To use this method, you will need to isolate the instances of the network adapter class that
contains the adapter with the valid IP address.
1. Run the following query from Exercise 2 to get the active network adapter. This will be
assigned to a variable for easy reference.
$mynic = Get-wmiobject query select * from win32_networkadapterconfiguration
where ipenabled = true

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 298 of 361

Now that the active network is assigned to the variable, you can easily execute the
method. However, just before you do that, verify that the variable contains the network
adapter of interest.
2. Run the following command to list the active network adapter:
$mynic

Note: If you do not see the active network adapter listed, then there is something
wrong with the query.

Now you are ready to set the DNS servers and the search order. The
setDNSServerSearchOrder method will accept an array of strings for the DNS servers.
If you are setting a single DNS server (which is not best practice) then you can use a
string for the single DNS server PowerShell will convert this to an array for the method
execution.
However if you are going to set multiple DNS servers and the search order, then you
need to supply an array of strings. The easiest way to do this is to create a variable with
the array of strings and then use this variable in the method call.
3. Run the following command to set the single DNS server value:
$mynic.SetDNSServerSearchOrder(192.168.0.1)

The return code should be zero indicating that the value has been changed. To verify the
result, you need to run the query again, as $mynic will reflect the configuration as the
time of assignment.
Get-wmiobject query select * from win32_networkadapterconfiguration where
ipenabled = true | format-list *

You will now see that the DNS servers have changed and will only be a single address. If
this is not the case, then look at the method call and result code to determine what has
gone wrong.
Now you will use a similar method to clear the current gateway value.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 299 of 361

Task 5: Set and Clear the Default Gateway Value


Using the setgateways method, you can also set the default gateway (and other gateways if
required). This method can also be used to clear the value. However, this is not obvious at
first. Similar to the setDNSSearchOrder method, this method can pass an array of address
for multiple gateways, or a single address for a single gateway. There is also an optional
parameter, the gatewaycost, which again is either a single value or an array of values for
multiple gateways.
To clear the gateway value, you need to supply the IP address of the local machine as the
gateway. If you supply a blank or null value to the method call, neither of these will work.
There is also no method to clear or delete the value.
1. Run the following command to clear the gateway value:
$mynic.setgateways(<local IP Address>)

Where <local IPaddress> is the IP address of the local machine.


2. Run the following command to verify the gateway has been changed:
Get-wmiobject -query "select * from win32_networkadapterconfiguration where
ipenabled = 'true'"

The default gateway should now be blank in the adapter properties or 0.0.0.0 under
PowerShell.
Now you need to set the value of this back to the previous value.
3. Run the following command to set the gateway value:
$mynic.setgateways(192.168.0.1)

4. Run the following command to verify the gateway has been changed:
Get-wmiobject -query "select * from win32_networkadapterconfiguration where
ipenabled = 'true'"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 300 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 10: Registry, Event Log and ACL
Management

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Lesson 10 Demonstration : Registry, Event Log and


ACL Management
Introduction
In the previous modules, you have learned about Windows Powershell fundamentals along
with WMI and Active Directory management.
The other important Windows constituents that administrators commonly manage are system
Registry, Event Logs and Access control lists (ACL) on the registry or file system.
Windows Powershell offers a cluster of cmdlets to manage Event Logs and ACLs.
The Registry provider lets you get, add, change, clear, and delete registry keys and values in
Windows PowerShell.
In addition, most of these integral components of Windows can also be managed using
Windows Powershell through select .Net and WMI classes.

Objectives
After completing this lab, you will be able to:

Manage the registry using the registry provider.

Access Remote registry using Windows Powershell.

Manage Event Logs and file system ACLs using Windows Powershell cmdlets.

Prerequisites
Windows 2008 server and Windows 7 workstation logged on to with domain administrator
credentials.

Estimated time to complete this lesson


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 302 of 361

Exercise 1: Using the Registry Provider


Objectives
In this exercise, you will:

Understand the usage of the registry provider.

Learn about the techniques to read, query, create, modify and delete registry keys/values
using the Windows Powershell registry provider.

Scenario
The Windows Powershell registry provider simplifies access to the registry by exposing the
hives as drives.
The registry provider provides access to the local registry keys and values. The registry
provider can be used to access a remote machines registry if used within a PS v2.0 Remote
session.
The Registry Provider allows us to access two PS Drives:

HKCU (HKEY_CURRENT_USER)

HKLM (HKEY_LOCAL_MACHINE)

The following command lists the PS Drives offered by the registry provider.
PS C:\> get-PSProvider registry
Name
---Registry

Capabilities
-----------ShouldProcess, Transactions

Drives
-----{HKLM, HKCU}

Additional registry PS drives can be created for a specific registry key:


New-PSDrive Run Registry "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
PS C:\> cd run:
PS Run:\>

In order to manage the registry items exposed by the provider, the following cmdlets are
designed to work with the data.
Name

Synopsis

Clear-ItemProperty

Deletes the value of a property but does not delete the property

Copy-ItemProperty

Copies a property and value from a specified location to another


location

Get-ChildItem

Gets the items and child items in one or more specified locations

Get-ItemProperty

Gets the properties of a specified item

Move-ItemProperty

Moves a property from one location to another

Get-Item

Gets the item at the specified location

New-Item

Creates a new item

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 303 of 361

Set-Item

Changes the value of an item to the value specified in the


command

Remove-Item

Deletes the specified items

Move-Item

Moves an item from one location to another

Rename-Item

Renames an item in a Windows PowerShell provider namespace

Copy-Item

Copies an item from one location to another within a namespace

Clear-Item

Deletes the contents of an item, but does not delete the item

New-ItemProperty

Creates a new property for an item and sets its value

Remove-ItemProperty

Deletes the property and its value from an item

Rename-ItemProperty

Renames a property of an item

Set-ItemProperty

Creates or changes the value of a property of an item

For example, in the drives that are supported by the Registry provider, you can use New-Item
to create a new registry key.
In the following sections of this exercise, we will demonstrate the following operations using
the registry provider:

Navigating the registry

Testing key existence

Reading registry properties

Creating registry keys

Creating registry properties

Modifying registry properties

Task 1: Log on to the VM environment


1. Log on to the Windows 7 client as Contoso\Administrator

Task 2: Navigating the registry using Windows Powershell Registry Provider


1. On the Windows task bar, locate and click the

icon.

This will open the Windows Powershell menu.


2. At the PS prompt, enter the following command to connect to the HKCU
(HKEY_CURRENT_USER) PSDrive.
PS C:\> cd hkcu:
PS HKCU:\>

3. List the sub keys in the HKCU hive using Dir or GCI.
PS HKCU:\> dir
Hive: HKEY_CURRENT_USER

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 304 of 361

SKC
--2
2
..

0
37
..

VC
Name
----AppEvents
Console

4. You can set the location (cd/sl) to any registry key as follows:
PS HKCU:\> cd software\microsoft\windows\currentversion\explorer
PS HKCU:\software\microsoft\windows\currentversion\explorer>

5. Similarly, you can directly set the location to a key in any of the registry providers
(HKLM: in the below command) from any other PS Drive.
PS HKCU:\> cd HKLM:\software\microsoft
PS HKLM:\software\microsoft>

Task 3: Testing registry key existence using the Registry Provider


In order to search for a registry key, you can use the cmdlets Get-ChildItem or Get-Item
1. Enter the below command (using GCI) with the full path to the registry location that you
want to check for existence.
PS HKLM:\> GCI hklm:\software\microsoft\windows
Hive: HKEY_LOCAL_MACHINE\software\microsoft\windows
SKC VC
--- -82
9
0
1
.. ..

Name
---CurrentVersion
DWM

Property
-------{SM_GamesName, SM_ConfigureProgramsName,
{UseDpiScaling}

Unlike Get-ChildItem, using get-item does not enumerate the sub keys, but only returns
the target Registry key.
PS HKLM:\> Get-Item hklm:\software\microsoft\windows
Hive: HKEY_LOCAL_MACHINE\software\microsoft

SKC
--12

VC Name
-- ---0 windows

Property
-------{}

2. To recursively search a registry key, the parameters recurse and include can be used as
follows:
PS HKLM:\> Get-childitem HKLM:\software -recurse -include Windows

This will find all the keys that contain the word "Windows" in the key names.
3. The Registry item returned, correspond to Microsoft.Win32.RegistryKey object that
provides the following associated member types.
PS HKLM:\> Get-item hklm:\software\microsoft\windows | Get-Member

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 305 of 361

TypeName: Microsoft.Win32.RegistryKey
Name
---Close
CreateObjRef
CreateSubKey
DeleteSubKey
DeleteSubKeyTree
DeleteValue
Equals
Flush
GetAccessControl
GetHashCode
GetLifetimeService
GetSubKeyNames
GetType
GetValue
GetValueKind
GetValueNames
InitializeLifetimeService
OpenSubKey
SetAccessControl
SetValue
ToString
Property
PSChildName
PSDrive
PSIsContainer
PSParentPath
PSPath
PSProvider
Name
SubKeyCount
ValueCount

MemberType
---------Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
NoteProperty
NoteProperty
NoteProperty
NoteProperty
NoteProperty
NoteProperty
NoteProperty
Property
Property
Property

Definition
---------System.Void Close()
System.Runtime.Remoting.ObjRef Crea..
Microsoft.Win32.RegistryKey CreateS..
System.Void DeleteSubKey(string sub..
System.Void DeleteSubKeyTree(string..
System.Void DeleteValue(string name..
bool Equals(System.Object obj)
System.Void Flush()
System.Security.AccessControl.Regis..
int GetHashCode()
System.Object GetLifetimeService()
string[] GetSubKeyNames()
type GetType()
System.Object GetValue(string name)
Microsoft.Win32.RegistryValueKind G..
string[] GetValueNames()
System.Object InitializeLifetimeSer..
Microsoft.Win32.RegistryKey OpenSub..
System.Void SetAccessControl(System..
System.Void SetValue(string name, S..
string ToString()
System.String[] Property=System.Str..
System.String PSChildName=CurrentVe..
System.Management.Automation.PSDriv..
System.Boolean PSIsContainer=True
System.String PSParentPath=Microsof..
System.String PSPath=Microsoft.Powe..
System.Management.Automation.Provid..
System.String Name {get;}
System.Int32 SubKeyCount {get;}
System.Int32 ValueCount {get;}

4. To enumerate a list of subkeys, enter the following command.


PS HKLM:\> (Get-item hklm:\software\microsoft\windows).getsubkeynames()
CurrentVersion
DWM
Help
HTML Help
ITStorage
ScheduledDiagnostics
ScriptedDiagnosticsProvider
Tablet PC
TabletPC
Windows Error Reporting
Windows Search
WindowsUp

5. To check if a Registry sub Key exists, you can also use the containment operator contains.
PS HKLM:\> (Get-item hklm:\software\microsoft\windows).getsubkeynames() -contains
"windows search"

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 306 of 361

True
PS HKLM:\>

In the above example, the output returns TRUE because the sub key named Windows
Search exists in the target parent key.

Task 4: Reading the Registry Properties


1. To enumerate the registry values inside a key, use the cmdlet Get-Itemproperty as shown
in the command that follows:
PS HKLM:\> Get-ItemProperty HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1
PSPath:Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\P
owerShell\1
PSParentPath:Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Micro
soft\PowerShell
PSChildName: 1
PSDrive: HKLM
PSProvider: Microsoft.PowerShell.Core\Registry
Install: 1
PID: 89383-100-0001260-04309
PS HKLM:\>

In the above output, you will notice that along with the registry values in the key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1, few of the
Powershell properties are also returned.
2. If you would like to determine the data contained in a particular value, use the value
name (as a) property in the output shown in the previous step.
In the following example, the data in the value named PID is obtained.
PS HKLM:\> $Regvalues= GP HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1
PS HKLM:\>$regvalues.pid
89383-100-0001260-04309
PS HKLM:\>

3. As shown below, you can also return the value data using the getvalue method on the key.
PS HKLM:\> (Get-Item HKLM:\SOFTWARE\Microsoft\PowerShell\1).getvalue("pid")
89383-100-0001260-04309
PS HKLM:\>

Task 5: Creating Registry Keys


1. The Cmdlet New-Item can be used to create a registry key.
Enter the below command containing the full path of the registry key that you want to
create.
PS HKLM:\> new-item hkcu:\software\MyApplication
Hive: HKEY_CURRENT_USER\software

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 307 of 361

SKC
--0

VC Name
-- ---0 MyApplication

Property
-------{}

PS HKLM:\>

2. The following syntax using the parameters path and name will create a registry key
named OurApplication".
PS HKLM:\> new-item -Path hkcu:\software -Name OurApplication
Hive: HKEY_CURRENT_USER\software

SKC
--0

VC Name
-- ---0 OurApplication

Property
-------{}

PS HKLM:\>

3. Alternatively, you can also run the following commands from the local path to create a
registry key.
PS HKCU:\software> New-Item yourApplication
Hive: HKEY_CURRENT_USER\software
SKC
--0

VC Name
-- ---0 yourApplication

Property
-------{}

PS HKCU:\software>

Or,
PS HKCU:\software> New-Item

-Path . -Name hisApplication

Hive: HKEY_CURRENT_USER\software
SKC
--0

VC Name
-- ---0 hisApplication

Property
-------{}

PS HKCU:\software>

Note: Use the cmdlet Remove-Item to delete registry keys.


For more information on how to use Remove-Item, obtain help on the cmdlet (help
remove-item full)

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 308 of 361

Task 6: Creating Registry Properties


1. To create registry values of different data types (REG_SZ, REG_MULTI_SZ,
REG_DWORD, REG_EXPAND_SZ, REG_QWORD, REG_BINARY), use the cmdlet
New-Itemproperty.
Note: This cmdlet does not add properties to an object. To add a property to an
instance of an object, use the Add-Member cmdlet. To add a property to all objects of a
particular type, edit the Types.ps1xml file.

2. Enter the command below to create a DWORD property named Config1 with a value of
1024 in the registry key MyApplication.
PS HKLM:\> New-ItemProperty HKCU:\Software\MyApplication -name "Config1" -value
"1024" -propertyType DWORD
PSPath
:
Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\MyApplication
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software
PSChildName : MyApplication
PSDrive
: HKCU
PSProvider
: Microsoft.PowerShell.Core\Registry
Config1
: 1024
PS HKLM:\>

The code above assumes that the registry key MyApplication exists prior to running the
command.
If the parameter -propertyType is not used, the registry value created will be of the data
type REG_SZ.
Note: Use the cmdlet Remove-ItemProperty to delete registry values.
For more information on how to use Remove-ItemProperty, obtain help on the cmdlet
(help remove-itemproperty full)

Task 7: Modifying Registry Properties


1. The cmdlet Set-ItemProperty can be used on a specified registry item to create or change
the value of a property.
The example shown below modifies the value of an existing DWORD property created
in the previous exercise to 2048.
PS HKLM:\> Set-ItemProperty path HKCU:\Software\MyApplication -name "Config1" value "2048"
PS HKLM:\>

If the DWORD property did not pre-exist, a new REG_SZ property with the value of
2048 would have been created.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 309 of 361

2. The parameterforce used with New-ItemProperty can also set/overwrite the value of an
existing registry property retaining its data type.
For example:
PS HKLM:\> New-ItemProperty path HKCU:\Software\MyApplication -name "Config1" value "4096" -force
PSPath
:
Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\MyApplication
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software
PSChildName : MyApplication
PSDrive
: HKCU
PSProvider
: Microsoft.PowerShell.Core\Registry
Config1
: 4096
PS HKLM:\>

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 310 of 361

Exercise 2: Remote Registry Management


Objectives
In this exercise, you will:

Understand the techniques of accessing remote registry using Powershell.

Learn how to read, query, create, modify and delete remote registry keys/values using
the .Net Framework RegistryKey class.

Scenario
In the previous exercise, we have learned how to access the local registry using the Windows
Powershell registry provider.
Though PowerShell 2.0 Remoting is the easiest way to deal with remote registry access, it
will only work in environments with PowerShell v2.0 installed and Windows Remote
Management (WINRM) allowed on the remote machines.
In this exercise, we will explore remote registry management using the Microsoft .Net
Framework Microsoft.Win32.Registry class.

Task 1: Connect to remote registry hive


1. To use the Microsoft.Win32.Registry class in PowerShell, access the
OpenRemoteBaseKey static method to connect to the required registry hive of a remote
computer.
The example below connects to the HKLM registry hive (LocalMachine) of the server
named syddc01.
$RemoteReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(LocalMachine,
Syddc01)

The commonly used registry hive names are as:

ClassesRoot HKEY_CLASSES_ROOT

CurrentUser HKEY_CURRENT_USER

LocalMachine HKEY_LOCAL_MACHINE

Users HKEY_USERS

PerformanceData HKEY_PERFORMANCE_DATA

CurrentConfig HKEY_CURRENT_CONFIG

DynData HKEY_DYN_DATA

2. The corresponding Microsoft.Win32.RegistryKey object (as created above) provides the


following associated member types to read, create, delete and change the registry key and
properties.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 311 of 361

PS C:\> $RemoteReg | Get-Member


TypeName: Microsoft.Win32.RegistryKey
Name
---Close
CreateObjRef
CreateSubKey
DeleteSubKey
DeleteSubKeyTree
DeleteValue
Equals
Flush
GetAccessControl
GetHashCode
GetLifetimeService
GetSubKeyNames
GetType
GetValue
GetValueKind
GetValueNames
InitializeLifetimeService
OpenSubKey
SetAccessControl
SetValue
ToString
Property
PSChildName
PSDrive
PSIsContainer
PSParentPath
PSPath
PSProvider
Name
SubKeyCount
ValueCount

MemberType
---------Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
Method
NoteProperty
NoteProperty
NoteProperty
NoteProperty
NoteProperty
NoteProperty
NoteProperty
Property
Property
Property

Definition
---------System.Void Close()
System.Runtime.Remoting.ObjRef Crea..
Microsoft.Win32.RegistryKey CreateS..
System.Void DeleteSubKey(string sub..
System.Void DeleteSubKeyTree(string..
System.Void DeleteValue(string name..
bool Equals(System.Object obj)
System.Void Flush()
System.Security.AccessControl.Regis..
int GetHashCode()
System.Object GetLifetimeService()
string[] GetSubKeyNames()
type GetType()
System.Object GetValue(string name)
Microsoft.Win32.RegistryValueKind G..
string[] GetValueNames()
System.Object InitializeLifetimeSer..
Microsoft.Win32.RegistryKey OpenSub..
System.Void SetAccessControl(System..
System.Void SetValue(string name, S..
string ToString()
System.String[] Property=System.Str..
System.String PSChildName=CurrentVe..
System.Management.Automation.PSDriv..
System.Boolean PSIsContainer=True
System.String PSParentPath=Microsof..
System.String PSPath=Microsoft.Powe..
System.Management.Automation.Provid..
System.String Name {get;}
System.Int32 SubKeyCount {get;}
System.Int32 ValueCount {get;}

The following sections of this exercise will cover the usage of the commonly used
methods and demonstrate the following remote registry operations:

Navigating the registry

Testing key existence

Reading registry properties

Creating registry keys

Creating registry properties

Modifying registry properties

Task 2: Log on to the VM environment


1. Log on to the Windows 7 client as Contoso\Administrator

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 312 of 361

Task 3: Navigating the remote registry


1. On the windows task bar locate and click the

icon.

This will open the Windows Powershell menu.


2. At the PS prompt, enter the following command to create the Microsoft.Win32.Registry
class object.
PS C:\> $RemoteReg =
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(LocalMachine, Syddc01)

The above variable stores information about the HKLM registry hive of the remote
computer Syddc01.
3. You can connect to any accessible sub key using the opensubkey() method
PS C:\> $dotnetreg = $RemoteReg.OpenSubKey("Software\Microsoft\NET Framework
Setup\NDP\v2.0.50727")
PS C:\> $dotnetreg
SKC
--23

VC Name
-- ---6

Property
--------

The opensubkey() method requires the subkey path parameter as a shown above.

Task 4: Testing remote registry key existence


1. In order to list the sub keys in a registry location use the getsubkeynames() method as
shown below
PS C:\> $RemoteReg =
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(LocalMachine, Syddc01)
PS C:\> $RemoteReg.GetSubKeyNames()
BCD00000000
HARDWARE
SAM
SECURITY
SOFTWARE
SYSTEM
PS C:\>

2. To determine the existence of a key, you can use the where-object filter on the list of
returned subkey names.
PS C:\> $psreg = $RemoteReg.OpenSubKey("SOFTWARE\Microsoft\PowerShell\1")
PS C:\> $psreg.getsubkeynames() | where {$_ -eq "ShellIds"}
ShellIds
PS C:\>

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 313 of 361

Task 4: Reading Remote Registry Properties


1. To enumerate the registry properties inside a key, use the GetValueNames() method on
the RegistryKey object.
In continuation to the above four commands, reuse the $psreg variable as follows:
PS C:\> $psreg.GetValueNames()
Install
PID
PS C:\>

2. If you would like to determine the data value contained in a particular property, use the
GetValue() method with the property name as a parameter to the method.
In the following example, the data in the property named PID is obtained.
PS C:\> $psreg.GetValue("pid")
89383-100-0001260-04309
PS C:\>

3. The following code lists all the registry value names and their associated data at a time
using the Foreach-Object loop.
PS C:\> $psreg.GetvalueNames()
Install : 1
PID : 89383-100-0001260-04309
PS C:\>

| foreach-object { "$_ : $($psreg.getvalue($_))"}

Task 5: Creating Remote Registry keys


1. At the PS prompt, enter the following command to connect to the remote registry of the
machine Syddc01.
PS C:\> $RemoteReg =
[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(LocalMachine, Syddc01)

2. While using the OpenSubKey() method, provide the optional Boolean argument to open
the subkey in R/W mode. However, it is always necessary to specify $true if you want to
add, delete, or modify values or keys in a particular registry hive.
In the following steps, a subkey will be created inside the target key
\Software\Microsoft.
PS C:\> $MSReg = $RemoteReg.OpenSubKey("Software\Microsoft, $true)
PS C:\>

3. Use the createsubkey() method to create a sub key in the target key
\Software\Microsoft.
PS C:\> $MSReg.CreateSubKey("MSData")
SKC VC Name
--- -- ---0
0
PS C:\>

Microsoft | Services

Property
--------

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 314 of 361

Note: Use the methods deletesubkey() or deletesubkeytree() to delete registry keys on


the RegistryKey class object.

Task 6: Creating Remote Registry properties


1. In the following example, you will create a DWORD property named State with the
value of 1 in the registry key MSdata created in the previous step.
Enter the following command to open the target sub key "Software\Microsoft\MSData
PS C:\> $MSDataReg = $RemoteReg.OpenSubKey("Software\Microsoft\MSData, $true)
PS C:\>

2. To create registry values of different data types use the method Setvalue() on the target
RegistryKey object.
PS C:\> $MSDataReg.setvalue("State", "1", "Dword")
PS C:\>

If the data type argument (third place) to the setvalue() method is not passed, the registry
value created will be of the type REG_SZ.

Task 7: Modifying Remote Registry properties


The method setvalue() can also set/overwrite the value of an existing registry property
retaining or changing its data type.
1. Run the following commands to change the value of the property State created in the
previous step and hence verify the update.
PS
1
PS
PS
2
PS

C:\> $MSDataReg.getvalue("State")
C:\> $MSDataReg.setvalue("State", "2", "Dword")
C:\> $MSDataReg.getvalue("State")
C:\>

Note: Use the method deletevalue() to delete a registry property on the RegistryKey
class object.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 315 of 361

Exercise 3: Eventlog Cmdlets


Objectives
In this exercise, you will:

Understand the techniques of managing local and remote Event Logs using Windows
Powershell.

Learn about how to read, write, clear and search event logs.

Scenario
Event Logs are special files that record significant events on your computer, such as, when a
user logs on to the computer or when a program encounters an error.
Starting with Windows Vista and Windows Server 2008 onwards, the operating system
includes two categories of event logs:

Windows Logs
Applications and Services logs

Windows Logs (Classic Event Logs)


The Windows Logs category includes the logs that were available on previous versions of
Windows: the Application, Security, and System logs. It also includes two new logs: the
Setup log and the ForwardedEvents log. Windows logs are intended to store events from
legacy applications and events that apply to the entire system.
Applications and Services Logs
Applications and Services logs are a new category of event logs. These logs store events from
a single application or component rather than events that might have system wide impact.
Windows Powershell provides two cmdlets Get-EventLog and Get-WinEvent to manage the
Classic and the newer event logs respectively.
On a Windows 2003 or Windows XP machine, you can only use the legacy Get-EventLog
cmdlet. On the other hand, Get-WinEvent can even read .etl, .evt, and .evtx log file formats

Task 1: Log onto the VM environment


1. Log on to the Windows 7 client as Contoso\Administrator

Task 2: The -EventLog cmdlets


A number of Windows PowerShell cmdlets provide functionality to manage the Windows
logs. The cmdlets that contain the EventLog noun (the EventLog cmdlets) work only on
classic event logs.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 316 of 361

To get events from logs that use the Windows Event Log technology in Windows Vista and
later versions of Windows, use Get-WinEvent, which is discussed in the next section of the
exercise.
1. Enter the following command to list the cmdlets that contain the EventLog noun.
PS C:\> gcm *-eventlog -CommandType cmdlet
CommandType
----------Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet
Cmdlet

Name
---Clear-EventLog
Get-EventLog
Limit-EventLog
New-EventLog
Remove-EventLog
Show-EventLog
Write-EventLog

Here is a synopsis of these cmdlets.


Clear-EventLog
Get-EventLog
Limit-EventLog
New-EventLog
Remove-EventLog
Show-Eventlog
Write-EventLog

Deletes all entries from specified event logs on the local or


remote computers
Gets the events in a specified event log or a list of the event
logs on a computer
Sets the event log properties that limit the size of the event
log and the age of its entries
Creates a new event log and a new event source on a local
or remote computer
Deletes an event log or unregisters an event source
Displays the event logs of the local or a remote computer in
Event Viewer
Writes an event to an event log

Note: All of the above cmdlets can be used with the computer parameter to manage
remote Windows event logs.

In the following examples, the common Event Log management scenarios will be
covered.
Read Windows Event Logs
1. On the windows task bar, locate and click the
Powershell menu.

icon. This will open the Windows

2. At the PS prompt, enter the following command to list the Windows event logs on the
machine.
PS C:\>

Get-EventLog -list

Max(K) Retain OverflowAction


------ ------ --------------

Microsoft | Services

Entries Log
------- ---

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 317 of 361

15,168
20,480
512
20,480
8,192
102,400
15,168
15,360

0
0
7
0
0

OverwriteAsNeeded
OverwriteAsNeeded
OverwriteOlder
OverwriteAsNeeded
OverwriteAsNeeded
0 OverwriteAsNeeded
0 OverwriteAsNeeded
0 OverwriteAsNeeded

21,119 Application
0 HardwareEvents
0 Internet Explorer
0 Key Management Service
0 Media Center
128,242 Security
40,729 System
19,372 Windows PowerShell

3. The command below lists the last 5 Netlogon errors reported in the System event log.
PS C:\> get-eventlog -newest 5 -logname System -entrytype Error Source Netlogon

Similarly, the other Windows event logs listed in Step (2) can be queried.
Write an event to an Event Log
If for instance, your script would like to write a log on the local or remote computer in the
event of a failure or success of an operation, the cmdlet, Write-EventLog, can be useful.
4. Enter the following command to write an Application Event Log with Event ID 10005
and Source VSS.
PS C:\> write-eventlog -logname Application -source VSS -eventID 10005 -entrytype
Warning -message "Unable to copy the backup. For help contact your system
administrator"

Clear event logs


5. The cmdlet, clear-cmdlet, deletes all entries from specified event logs on the local or
remote computers.
clear-eventlog -log application, system confirm computer syddc01

The above syntax will clear the Application and System event logs from the remote
computer named syddc01.

Task 3: Get-WinEvent cmdlet


As the format of event logs has changed considerably in Windows Vista and later operating
systems, Powershell now includes a cmdlet, Get-WinEvent, directly targeted at enumerating
these logs including remote computers.
1. You can continue to access the classic event logs by specifying their name as an
argument to the LogName parameter of the cmdlet as shown below:
PS C:\> Get-WinEvent -LogName System computer syddc01

2. The Get-Winevent cmdlet provides more information on the event log properties.
PS C:\>

get-winevent -listlog System | format-list -property *

FileSize
IsLogFull
LastAccessTime
LastWriteTime
OldestRecordNumber
RecordCount

Microsoft | Services

:
:
:
:
:
:

16912384
False
6/24/2011 5:53:56 PM
10/5/2011 11:02:23 AM
147781
40761

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 318 of 361

LogName
LogType
LogIsolation
IsEnabled
IsClassicLog
SecurityDescriptor

:
:
:
:
:
:

System
Administrative
System
True
True
O:BAG:SYD:(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x
;;;SU)(A;;0x1;;;S-1-5-3)(A;;0x2;;;S-1-5-33)(A;
LogFilePath
: %SystemRoot%\System32\Winevt\Logs\System.evtx
MaximumSizeInBytes
: 15532032
LogMode
: Circular
OwningProviderName
:
ProviderNames
: {ACPI, adp94xx, adpahci, adpu320...}
ProviderLevel
:
ProviderKeywords
:
ProviderBufferSize
: 64
ProviderMinimumNumberOfBuffers : 0
ProviderMaximumNumberOfBuffers : 16
ProviderLatency
: 1000
ProviderControlGuid
:

3. To read the log by the name "Microsoft-Windows-Dhcp-Client/Admin" in the


Application and Services Logs category, enter the command as:
PS C:\> get-winevent -logname
10

"Microsoft-Windows-Dhcp-Client/Admin" Maxevents

As specified in the maxevents parameter, the output above will return a maximum of 10
events only.
4. Enter the following command to list the providers that write to the System log.
PS C:\> (get-winevent -listlog System).providernames

Task 4: Searching for Event Log entries


The Event Logs can be queried based on several criteria. Inversely, you can filter based on
the required properties to search for the occurrences of Events.
1. List the properties on the object returned by the Get-EventLog cmdlet.
PS C:\> Get-EventLog system -Newest 2 | gm -MemberType property
TypeName: System.Diagnostics.EventLogEntry
Name
---Category
CategoryNumber
Container
Data
EntryType
Index
InstanceId
MachineName
Message
ReplacementStrings
Site
Source
TimeGenerated

Microsoft | Services

MemberType
---------Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 319 of 361

TimeWritten
UserName

Property
Property

2. List the properties on the System.Diagnostics.Eventing.Reader.EventLogRecord object


returned by the Get-WinEvent cmdlet.
PS C:\> Get-WinEvent system

-MaxEvents 2

| gm membertype Property

TypeName: System.Diagnostics.Eventing.Reader.EventLogRecord
Name
---ActivityId
Bookmark
ContainerLog
Id
Keywords
KeywordsDisplayNames
Level
LevelDisplayName
LogName
MachineName
MatchedQueryIds
Opcode
OpcodeDisplayName
ProcessId
Properties
ProviderId
ProviderName
Qualifiers
RecordId
RelatedActivityId
Task
TaskDisplayName
ThreadId
TimeCreated
UserId
Version

MemberType
---------Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property
Property

PS C:\>

3. Searching for Event Log entries based on a search filter.


get-eventlog -log system -source Time-Service | where {$_.eventID -eq 129 and
$_.message like *not found*"}

The command above will search the System log for source Time-Service that has an
Event ID 129 and contains the not found message description.
4. Using the FilterHashTable parameter with Get-WinEvent cmdlet.
This uses a query in hash table format to select events from one or more event logs.
Run the commands below to filter the Windows Powershell logs for Event Id 400
logged since the previous day.
C:\PS> $yesterday = (get-date) - (new-timespan -day 1)
C:\PS> get-winevent -FilterHashTable @{LogName='Windows PowerShell'; id=400;
StartTime=$yesterday}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 320 of 361

Exercise 4: File and Folder ACL Management


Objectives
In this exercise, you will:

Learn about how to read, copy, write and modify ACLs on Files & Folders using
Windows Powershell cmdlets.

Scenario
The file and folder access authorization is controlled using an access control list (ACL) on the
object. The ACL is a list of entries (called the Access Control Entry: ACE) that identifies
trustees and specifies the access rights allowed, denied, or audited for those trustees.
In easier terms, the ACL specifies the permissions that users and user groups have to access
the resource.
Several commands line utilities like cacls, xcacls, icacls can be used to verify and modify the
access permissions on files and directories.
Windows PowerShell uses the cmdlets, Get-Acl und Set-Acl, to manage the permissions.

Task 1: Log on to the VM environment


1. Log on to the Windows 7 client as Contoso\Administrator

Task 2: Reading ACLS


The cmdlet, Get-ACL, gets the security descriptor for a resource, such as a file, folder or
registry key.
While getting the access permissions on a file or folder, it creates a security descriptor object
of the class System.Security.AccessControl.FileSecurity or
system.Security.AccessControl.DirectorySecurity
1. Run the command below to get the ACL on the Windows directory.
PS C:\>

get-acl $env:windir | ft -AutoSize Wrap

2. To list the detailed access permissions, run the following command.


PS C:\> (

get-acl C:\Windows).access | ft -wrap

Task 3: Copying ACLS


The Set-Acl cmdlet changes the security descriptor on a file or a folder, to match the values
in a security descriptor that you supply.
The Set-Acl cmdlet, uses the -AclObject parameter to apply a security descriptor on the
desired resource.
In the following example, the ACL on a source directory would be copied to another
directory.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 321 of 361

Note: The folders named Source and Destination need to be created with different
set of permissions before following the below steps.

1. Use the get-acl cmdlet to store the ACL of the source directory in a variable.
$sourceacl = Get-acl c:\Source

2. Next apply the ACL in $sourceacl to the destination directory by running the following
command.
Set-acl path c:\destination aclObject $sourceacl

Task 4: Creating and modifying ACLS


You can set permissions on files and folders by using the Set-ACL cmdlet but would also
involve creating the security descriptor object specifying the
System.Security.AccessControl.FileSystemAccessRule class.
In this example, the ACL on the folder c:\destination will be modified.
1. Get the current ACL of the folder using Get-ACL as follows:
PS C:\> $destacl = Get-ACL c:\destination

2. Create the System.Security.AccessControl.FileSystemAccessRule object as follows:


$aclrule = New-Object
system.security.accesscontrol.filesystemaccessrule("administrators", "Read",
"Allow")

3. Set the access rule object $aclRule to the existing access rule object $destacl using the
SetAccessRule() method.
PS C:\> $destacl.setaccessrule($aclrule)

4. Hence, the command below will apply the modified ACL to the destination folder.
PS C:\> Set-ACL c:\destination aclobject $destacl

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 322 of 361

Lesson 10 Hands-On : Registry, Event Log and ACL


Management
Objectives
The objectives for this lab are:

To search the Event Log for specific entries.

To check the registry of remote machine and modify values.

To configure permissions on a folder.

Prerequisites

The lab requires a windows 7 client running in a domain environment.

Estimated time to complete this lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 323 of 361

Exercise 1: Reading Registry Information from a


Remote Host
Objectives
In this exercise, you will:

Read the registry values of a remote machine for Internet Explorer details.

Create a remote Reg key and create values.

Duration
15 minutes

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Task 2: Open Windows PowerShell Session


On the windows task bar, locate the

icon. Click this icon.

The PowerShell window will open.

Task 3: Read the registry on a remote machine.


1. Create a file named c:\pshell\part1\lesson10\labs\lab1-ex1.ps1 with notepad, or the ISE.
2. On the first line enter the following:
$servers = get-content c:\pshell\part1\lesson10\labs\servers.txt

3. On the next line, enter the following:


$regpath = software\microsoft\internet explorer

4. On the next line, enter the following:


Foreach ($server in $servers)

5. On the next line, enter the following:


{

6. On the next line, enter the following:


Write-host Checking server: $server foregroundcolor green

7. On the next line, enter the following:


$reg = [Microsoft.win32.registrykey]::openremotebasekey(LocalMachine,$server)

8. On the next line, enter the following:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 324 of 361

$regkey = $reg.opensubkey($regpath)

9. On the next line, enter the following:


$values = $regkey.getvaluenames()

10. On the next line, enter the following:


Write-host Checking Internet Explorer details

11. On the next line, enter the following:


Foreach ($value in $values)

12. On the next line, enter the following:


{

13. On the next line, enter the following:


Write-host $value : $($regkey.getvalue($value))

14. On the next line, enter the following:


}

15. On the next line, enter the following:


}

16. Save your script:


17. Open the text file c:\pshell\part1\lesson10\labs\servers.txt
You will see in this file contain SYDDC01and W7Client.
18. Now execute the saved script in PowerShell.
You will see that the details for Internet Explorer for each machine displayed.

Task 4: Create a remote registry key and values


1. Now save the script file as lab10-Ex1a.ps1.
2. Change the line $regpath

= software\microsoft\internet explorer

to the code below:

$regpath = software

3. Modify the line $regkey

= $reg.opensubkey($regpath)

as follows:

$regkey = $reg.opensubkey($regpath,true)

Note: The parameter is added to the command to allow the key to be written to.

4. Replace the line $values

= $regkey.getvaluenames()

with the following code:

$contoso = $regkey.opensubkey("contoso",true)

5. On the next line, enter the following:

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 325 of 361

if ($contoso -eq $null) {$contoso = $regkey.createsubkey("contoso")}

The line above will create the registry key if it does not already exist.
6. On the next line, enter the following:
$serialnumber = (get-wmiobject win32_bios -computer $server).serialnumber

The line above will extract as text the value of the serial number in bios.
7. On the next line, enter the following code.
$contoso.SetValue("serialnumber",$serialnumber)

The line above will create the registry value, serial number, and the value will be the
value in the $serialnumber variable.
8. On the next line, enter the following lines of code.
$values = $contoso.getvaluenames()
write-host "$server has the registry key HKLM:\software\Contoso if it didnt
already"
write-host "The following registry values exist under this key"

9. Delete the line Write-host

Checking internet explorer details

10. The next two lines of code should appear as follows:


Foreach ($value in $values)
{

Do not change these lines.


11. Modify the line of code Write-host
following code.

$value : $($regkey.getvalue($value))

to the

Write-host $value : $($contoso.getvalue($value))

12. The following two lines of code should complete the script.
}
}

13. Save your script and execute it in PowerShell.


You should now see displayed the registry key and the values for each machine.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 326 of 361

Exercise 2: Searching Event Logs for Events


Objectives
In this exercise, you will:

Search the Eventlog for specific entries.

Duration
15 minutes

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password P@ssword

Task 2: Open Windows PowerShell Session


On the windows task bar, locate the

icon. Click this icon.

The PowerShell window will open.

Task 3: Create a script to search the eventlog.


1. Create a file named c:\pshell\part1\lesson10\lab10\lab10-Ex2.ps1 with notepad, or the
ISE.
2. On the first line enter the following.
$systemerrors= c:\pshell\part1\lesson10\labs\systemerrors.csv

3. On the next line, enter the following.


$apperrors = c:\pshell\part1\lesson10\labs\apperrors.csv

The variables above will be used to store the paths to the files where error events from
the system log and application will be written.
4. On the next line, enter the following.
$sysevents = get-winevent logname system | where-object {$_.id eq 12} | selectobject first 1 property timecreated

The line above will search the eventlog for event ID 12, which is the operating system
started. The select-object cmdlet using the first parameter gets the last occurrence on
this. This event ID can be used as a flag for the last boot as far as Eventlog entries go.
5. On the next line, enter the following.
$lastreboot = $($sysevents.timecreated)

The line above extracts the time on the startup event. This will be used in the following
lines to search for events after that time.
6. On the next line, enter the following.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 327 of 361

$sysevents = get-winevent -logname system | where-object {$_.Timecreated -gt


$lastreboot} | where-object {$_.LevelDisplayName -eq 'Error' -or
$_.leveldisplayname -eq 'Critical'}

The line above will search the system log for any errors that have occurred after the time
in $lastreboot.
7. On the next line, enter the following.
$count = ($sysevents | Measure-Object).count

8. On the next line, enter the following.


If ($count gt 0)

9. On the next line, enter the following.


{

10. On the next line, enter the following.


Write-host $count Errors were found in the system eventlog. Details in the file
$systemerrors

11. On the next line, enter the following.


$sysevents | export-csv $systemerrors notypeinformation

12. On the next line, enter the following.


}

This will close the first part of the if statement.


13. On the next line, enter the following.
else

14. On the next line, enter the following.


{

15. On the next line, enter the following.


Write-host No errors were found in the system eventlog after bootup at
$lastreboot

16. On the next line, enter the following.


}

This will complete the if statement and else section. The code above will not only search
for error in the system log, but will also export them to a csv file. If there are no errors
then this will also be indicated.
17. Save your script and execute it in PowerShell.
You will see that script will run and inform you of any errors that are in the system log.
Note: You may not find any errors in the system after reboot. If you dont see any errors
detected then check the system log to see if this is actually the case.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 328 of 361

18. Open the c:\pshell\part1\lesson10\labs\systemerrors.csv using notepad. You will see the
details of the event log entries in this file.
19. Open the script again in notepad or the ISE.
20. Copy the following lines of code.
$sysevents = get-winevent -logname system | where-object {$_.Timecreated -gt
$lastreboot} | where-object {$_.LevelDisplayName -eq 'Error' -or
$_.leveldisplayname -eq 'Critical'}
$count = ($sysevents | Measure-Object).count
If ($count gt 0)
{
Write-host $count Errors were found in the system eventlog. Details in
the file $systemerrors
$sysevents | export-csv $systemerrors -notypeinformation
}
else
{
Write-host No errors were found in the system eventlog after bootup at
$lastreboot
}

21. Paste these below the original section.


22. Change the code to match the following. In bold are the text that needs to change.
$appevents = get-winevent -logname application | where-object {$_.Timecreated -gt
$lastreboot} | where-object {$_.LevelDisplayName -eq 'Error' -or
$_.leveldisplayname -eq 'Critical'}
$count = ($appevents | Measure-Object).count
If ($count gt 0)
{
Write-host $count Errors were found in the Application eventlog. Details in
the file $apperrors
$appevents | export-csv $apperrors -notypeinformation
}
else
{
Write-host No errors were found in the Application eventlog after bootup at
$lastreboot
}

The above code should now look at the application log for Critical or Error levels since
the last reboot.
23. Save your script and execute it in PowerShell.
You will see that script will run and inform you of any errors that are in the system log.
24. Open c:\pshell\part1\lesson10\labs\apperrors.csv using notepad. You will see the details
of the event log entries in this file.

Task 4: Optional Additional exercise.


1. Open the script in notepad or the ISE.
2. Modify the script to also look at the system log for warning entries and the application
log warning events as well. You can use a similar process as above to perform these
actions.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 329 of 361

Note: You will need new variables and files to store the warning events in.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 330 of 361

Exercise 3: File and Folder ACL Management


Objectives
In this exercise, you will:

Read the permissions on a folder.

Set the permissions on a folder.

Duration
15 minutes

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client as Contoso\Administrator with Password
P@ssword

Task 2: Open Windows PowerShell Session


On the windows task bar, locate the

icon. Click this icon.

The PowerShell window will open.

Task 3: Read folder permissions


1. In the PowerShell console, enter the following.
New-item c:\userdata type directory

This will create a new folder off the root of the C drive. This folder will inherit the
default permissions.
2. In Windows explorer, check the folder permissions by right-clicking the folder, selecting
Properties and checking the Security tab.
Note: The permissions of the built in users group will have read and execute, list folder
contents and read. These are inherited permissions so the ticks are grey.

3. In the PowerShell console, enter the following command.


$acl = get-acl C:\userdata

This will read the access control lists for the object and assign them to the $acl variable.
4. Enter the following command.
$acl.access

This will now display the access control lists for users and their permissions.
In order to be able to change permissions such as removing a user from access, you need
to remove the inherence from the parent folder.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 331 of 361

Task 4: Clear inheritance


1. Enter the following command to remove the inheritance.
$acl.setaccessruleprotection($true,$true)

The above command modifies the access control list, however, this is not applied to the
folder. To do this, you must set the ACL back to the folder.
2. Enter the following command to apply the modified ACL to the folder.
$acl | set-acl c:\userdata

The permission inheritance will now be removed.


3. In Windows explorer, check the folder permissions by right-clicking the folder, selecting
Properties and checking the Security tab.
Note: The permission ticks are now solid black. This indicates that the permissions are
set on the folder level and not inherited.

Task 5: Remove permissions


1. Enter the following command to retrieve the current ACLs for the folder.
$acl = get-acl c:\userdata

Now you will have the current acls in the $acl variable. Now we can remove a specific
users permissions from the object. First you must get the specific user ACL.
2. Enter the following command to get the BUILTIN\users ACL.
$useracl = $acl.access | where {$_.identityreference -eq "BUILTIN\Users"}

3. Enter the following to view the ACL.


$useracl

4. Enter the following to remove the ACL from the ACL list.
$acl.RemoveAccessRule($useracl)

This will remove the builtin\users acl from the list of ACLs. Once this is done the ACL
list in the $acl variable can be applied to the object.
5. Enter the following to view the ACL list.
$acl.access

6. Enter the following command to set the ACLs on the folder.


$acl | set-acl c:\userdata

7. In Windows explorer, check the folder permissions by right-clicking the folder, selecting
Properties and checking the Security tab.
Note: The builtin\users group is now removed from the permissions of the folder and
now, you will grant the BUILTIN\users group full control to the folder.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 332 of 361

Task 6: Create an ACL


1. Enter the following to set the inheritance options for the folder.
$inheritance = 3

The values for this can be 0 for none, 1 for containerinherit and 2 for ObjectInherit. The
value used above is 3, which is both container and object inherit.
2. Enter the following to set the propagation options for the folder.
$propagation = 0

The values for this can be 0 for none, 1 for NoPropagateInherit and 2 for Inheritonly.
The value used above is 0, which is none.
3. Enter the following to create an array for the new ACL.
$newacl = "BUILTIN\Users","fullcontrol",$inheritance,$propagation,"allow"

The above is an array of strings. This specifies the user account, the permissions required,
the inheritance and propagation flags and finally if the permissions are allowed or denied.
4. Enter the following to create the new ACL object.
$accessrule = new-object
system.security.accesscontrol.filesystemaccessrule($newacl)

5. Enter the following command to add the new ACL object to the ACL list.
$acl.AddAccessRule($accessrule)

6. Enter the following to list the ACLs.


$acl.access

This will now display the ACLs to be applied to the file.


7. Enter the following command to apply the ACLs to the object.
$acl | set-acl c:\userdata

8. In windows explorer, check the folder permissions by right-clicking the folder, selecting
Properties and checking the Security tab.
You will note that the BUILTIN\Users will now have full control of the folder.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 333 of 361

PowerShell for the IT


Administrator, Part 1
Lesson 11: PowerShell Remoting

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 334 of 361

Lesson 11 Demonstration : Remoting


Introduction
The majority of a system administrator's tasks involve managing a wide range of
machines. Many tasks require the same action or information to be executed or obtained
from multiple machines. This can be done locally at each machine. However, the most
efficient way involves being able to manage these machines remotely and running your
code from a centralized location.
This lesson covers managing remote machines using the PowerShell Cmdlets supporting
the -ComputerName parameter and using PowerShell remoting through Cmdlets that
interact with the WinRM 2.0 service.

Objectives
After completing this lesson you will be able to:

Understand remote management without PowerShell remoting

Understand PowerShell remoting and WS-Management

Understand remoting requirements and configuration

Use the invoke-command for executing one-off commands

Work with PowerShell sessions to:

Use a persistent remote session for executing a series of commands

Use an interactive remote session

Create a session configuration

Use background jobs with remoting

Understand remoting security and authentication, including:

Active directory group policy object settings

Kerberos, Negotiate, CredSSP and Basic authentication

Traffic Encryption

Prerequisites

A windows 7 workstation logged onto with administrator credentials

A domain controller, SYDDC01

Estimated time to complete this lesson


60 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 335 of 361

Exercise 1: Remote Management without PowerShell


Remoting
Objectives
In this exercise, you will:

Identify Cmdlets that have the -ComputerName parameter

Use Cmdlets with the -ComputerName parameter

Use WMI for remote management

Scenario
In this exercise, you will understand remote management without the use of PowerShell
remoting. This can be very useful in the environment where PowerShell remoting is not
enabled.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Windows PowerShell


Click the

icon on the Windows task bar

The PowerShell window will open.

Task 1: Identify Cmdlets with the -ComputerName Parameter


1. Type the following command.
get-command | where { $_.parameters.keys -contains "computername" -and
$_.parameters.keys -notcontains "session"}

This command lists all commands that contain the ComputerName parameter. It
excludes any command that also contains Session as a parameter. The Session
parameter is associated with commands that relate to PowerShell remoting. The
objective of this exercise is to perform remote management without the use of the
PowerShell remoting feature.

Task 2: Using Cmdlets with the -ComputerName Parameter


1. Type the following command.
get-eventlog -computername syddc01 -log system -newest 10

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 336 of 361

This command returns the ten newest events in the system event log on the domain
controller machine (SYDDC01).
2. Type the following command.
get-hotfix -computername syddc01,w7client

This command returns all the hotfixes on both the domain controller (SYDDC01) and
the Windows 7 client.
Note: Single or multiple machine names can be specified as parameter arguments
to the ComputerName parameter.

Try the following command:


get-hotfix -cn syddc01,w7client

Where, cn is an alias for the ComputerName parameter.


3. Type the following command.
syddc01,w7client > $home\documents\servers.txt

Now type the following command.


get-hotfix -computername (get-content $home\documents\servers.txt)

The first command creates a servers.txt file in the current users documents directory
using the $home automatic variable. The second command returns all the hotfixes on
both the syddc01 and w7client machines. The get-content Cmdlet is used to retrieve
the machine names from a text file in this example.

Task 3: Using WMI for Remote Management


WMI also includes built-in remote management functionality that can be used
independently from PowerShell remoting.
1. Type the following command.
get-wmiobject win32_operatingsystem -computername syddc01

Operating System information related to machine syddc01 is displayed in the console.


get-wmiobject win32_operatingsystem `
-computername syddc01,w7client

Operating system information related to both syddc01 and w7client is displayed in


the console. The back tick or grave character (`) is used in this instance to escape the
newline character that separates the first part of the command from the second part.
This can be useful to facilitate readability when typing long commands into either a
console or a script file.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 337 of 361

Note: Either the machine name or IP address can be specified as the parameter
arguments for the ComputerName parameter.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 338 of 361

Exercise 2: Enable PowerShell Remoting


Objectives
In this exercise, you will:

Verify if PowerShell remoting is available

Enable PowerShell remoting

Scenario
PowerShell remoting is useful for running commands or scripts that do not have built-in
remote management capabilities. PowerShell remoting allows you to remotely manage
machines using the underlying Web Services for Management (WS-Management)
protocol implemented in the WinRM service.
WS-Management is an industry standard management protocol based on the Simple
Object Access Protocol (SOAP). The WS-Management protocol was developed by a
group of hardware and software manufacturers as a public standard for remotely
exchanging management data with any computer device that implements the protocol.
WinRM 2.0 is Microsoft implementation of the WS-Management protocol.

PowerShell Remoting Requirements


The following components are required on both the local machine and remote
machine(s):

Windows PowerShell 2.0 or later

Microsoft .NET Framework 2.0 or later

Windows Remote Management (WinRM) 2.0

WinRM 2.0 is by default included in Windows 7 and in Windows Server 2008 R2. For
operating systems other than Windows 7 and Windows 2008 R2 Server the Windows
Management Framework package can be downloaded from
http://support.microsoft.com/default.aspx/kb/968929. This package will install Windows
PowerShell 2.0, WinRM 2.0, and BITS 4.0. The update can be installed on the following
operating systems:

Windows Server 2008 Service Pack 2 (SP2)

Windows Vista SP 1 and 2

Microsoft Windows Server 2003 SP 2

Microsoft Windows XP SP 3

An administrator must explicitly enable and configure PowerShell remoting before it can
be used.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 339 of 361

Note: Windows PowerShell Integrated Scripting Environment (ISE) and the OutGridview Cmdlet require the Microsoft .NET Framework 3.5 with Service Pack 1.
The Get-WinEvent cmdlet requires the Microsoft .NET Framework 3.5 or greater.
This version of the Microsoft .NET Framework is however not required for
PowerShell remoting.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


To open an elevated Windows PowerShell session:
1. Right-click the

icon on the Windows task bar.

2. Select Run As Administrator.


3. Click Yes if a User Account Control Prompt appears
The PowerShell window will open.

Task 1: Verify PowerShell Remoting


1. Type the following command to verify whether or not the service is running.
get-service -computername syddc01,w7client | where{$_.name -eq "winrm"} |
select name,machinename,status | sort machinename | ft -autosize

Task 2: Enable PowerShell remoting


1. Type the following command to enable PowerShell remoting.
enable-psremoting

2. Type Y to continue.
3. Type the following command to verify that the service is running
get-service winrm

4. Type the following command to view additional details about the WinRM client
configuration.
winrm get winrm/config/client

5. Repeat the steps above on machine syddc01.


Note: The enable-psremoting Cmdlet does not support the ComputerName
parameter.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 340 of 361

Exercise 3: Enable PowerShell Remoting with the


Active Directory Group Policy Object (GPO)
Objectives
In this exercise, you will:

Explore the AD GPO configuration settings for WinRM.

Scenario
The Enable-PSRemoting Cmdlet does not include support for the ComputerName
parameter. As a result, it is not an efficient solution to enable PowerShell remoting for
large numbers of machines. Two common methods to do this are:
1. Use the Enable-PSRemoting Cmdlet with the -Force switch to suppress user
prompts in a logon script.
2. Use group policy objects.
Example GPO Configuration:
Computer Configuration
Administrative Templates
Network/NetworkConnections/Windows Firewall/Domain Profile
Policy Name - Windows Firewall: Define inbound Port Exceptions
Setting - Enabled
Define Port Exceptions - 5985:TCP:*:enabled:WS-Man Listener Port 5985
Windows Components/Windows Remote Management (WinRM)/WinRM Service
Policy Name - Allow automatic configuration of listeners
Setting Enabled
IPv4 Filter *
IPv6 Filter *
Windows Components/Windows Remote Shell
Policy Name - Allow Remote Shell Access
Setting Enabled

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Task 1: Open GPO and Explore Configuration Settings


1. On the domain controller SYDDC01, type gpedit.msc at a command prompt.
The Group Policy Object Editor window opens.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 341 of 361

2. Look for the Doman Profile GPO under Administrative Templates, Network,
Network Connections and Windows Firewall.
The Windows Firewall: Define inbound Port Exceptions setting can be used to
enable an inbound firewall exception for the WS-Management listener service on
port 5985 for the TCP protocol.
3. Look for the Windows Remote Management and Windows Remote Shell GPOs
under Administrative Templates and Windows Components.
The Allow automatic configuration of listeners setting allows automatic
configuration of the WS-Management listener port for all machines. A wildcard (*)
for each filter allows messages from many remote machines. This can alternatively
be populated with a comma-separated list or dash-separated range of IP v4 or IP v6
addresses.
The Allow Remote Shell Access setting allows remote shell access to the machine.
Note: The Windows Remote Management GPO also allows setting the
authentication protocol. The options are Kerberos, Negotiate, CredSSP and Basic.
The default authentication protocol is Kerberos for domain joined machines and
NTLM for non-domain joined machines.
The authenticating protocol (either Kerberos or NTLM) is dynamically selected
using negotiate authentication. Disabling negotiate authentication will effectively
disable NTLM authentication.
All WinRM traffic is encrypted by default. Unencrypted traffic can be enabled using
the Allow unencrypted traffic GPO setting.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 342 of 361

Exercise 4: Execute a Single Remote Command or


Script
Objectives
In this exercise, you will:

Execute a single remote command

Execute a single remote script

Use a background job to run a single remote command

Scenario
To run a command on remote machines on a one-time-only basis, use Invoke-Command.
This Cmdlet can accept a list of remote computer names in its ComputerName
parameter. The command to actually run on the remote machine is in the form of a
scriptblock and therefore, enclosed in curly braces.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


To open an elevated Windows PowerShell session:
Right-click the

icon on the Windows task bar.

1. Select Run As Administrator.


2. Click Yes if a User Account Control Prompt appears.
The PowerShell window will open.

Task 1: Execute a Single Remote Command


1. Type the following command.
invoke-command -computername syddc01,w7client -scriptblock {get-process}

Process information related to both the syddc01 and w7client machines are returned.
Note that a PSComputerName column is added to the output.

Task 2: Execute a Single Remote Script


1. Type the following command.
get-process > $home\documents\single_remote_script.ps1

2. Type the following command.


Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 343 of 361

invoke-command -computername syddc01,w7client -filepath


$home\documents\single_remote_script.ps1

The first command creates a single_remote_script.ps1 file in the current users


documents directory using the $home automatic variable. The second command uses
the -FilePath parameter to specify the newly created script that is stored locally. The
script returns process information related to both the syddc01 and w7client machines.

Task 3: Use a Background Job to Run a Single Remote Command


1. Type the following command.
$command = {gwmi -query select name,status,manufacturer,biosversion from
win32_bios | fl name,status,manufacturer,biosversion,pscomputername}

This command stores a query in a variable for use in the next command.
2. Type the following command
$job = invoke-command -computername syddc01,w7client -ScriptBlock $command ThrottleLimit 2 -AsJob

Jobs can also be used in conjunction with PowerShell remoting. A long-running job
run against many machines can be executed in a background thread so that control is
immediately returned to the shell and the user can continue with another task. To do
this, include the -AsJob parameter in the Invoke-Command Cmdlet and save the
command to a variable reference.
3. Type the following command.
$job

This command retrieves information about the job.


4. Type the following command.
$job.childjobs

To view the results of child jobs, use the childjobs property of the $job object.
5. Type the following command.
receive-job -name job2 -keep

Use the Receive-Job Cmdlet to view the information returned from each remote
machine. The keep parameter is used to keep the data available for future retrieval
using the receive-job Cmdlet.
Note: It is possible for the job number to be different. Take note of the job names
that are displayed after step 4 above.

6. Type the following command.


get-job | remove-job

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 344 of 361

This command removes all jobs.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 345 of 361

Exercise 5: Create a Persistent Session to Execute a


Series of Remote Commands
Objectives
In this lesson, you will:

Create a persistent session and then proceed to run commands and scripts against this
session

Use variables created in one command from another command that runs from the
same session

Scenario
The Invoke-Command approach is useful for one-off commands. However, if you want
to run a series of commands against remote machines and store variables that you can
access later, you need to use the PowerShell remoting concept of a session, which is
persisted between commands. The New-PSSession Cmdlet enables the creation of a new
persistent PowerShell run space on a remote computer, which is not destroyed every time
a command is issued.
You can specify a single or multiple machines to create sessions with and run a command
against each session.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


To open an elevated Windows PowerShell session:
1. Right-click the

icon on the Windows task bar.

2. Select Run As Administrator.


3. Click Yes if a User Account Control Prompt appears.
The PowerShell window will open.

Task 1: Create and Use a Persistent Session


1. Type the following command.
$mysession = new-pssession -computername syddc01,w7client

This command specifies multiple machines to create a session with. A variable is


used to store the session information.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 346 of 361

2. Type the following command to view information related to the session.


$mysession

Note the session identifiers.


3. Type the following command.
invoke-command -session $mysession -scriptblock {$env:processor_architecture}

This command uses the session that was created in step 1 and retrieves the processor
architecture for both the syddc01 and w7client machines. Note that the session is not
destroyed and can be used again.
4. Type the following command.
$session1 = get-pssession -id 1

The Get-PSSession Cmdlet allows you to get a reference to these sessions by their
identifier property.
5. Type the following command to list information related to the session identifier.
$session1

6. Type the following command.


$session2 = get-pssession -id 2

The Get-PSSession Cmdlet allows you to get a reference to these sessions by their
identifier property.
7. Type the following command to list information related to the session identifier.
$session2

8. Type the following command to run a command against a specific session identifier
as opposed to against all session identifiers that were created during step 1 in the
$mysession variable.
invoke-command -session $session1 -scriptblock {$env:computername}

9. Type the following command to return the ComputerName that relates to the other
session.
invoke-command -session $session2 -scriptblock {$env:computername}

10. In this example, you will create a variable in one command and then demonstrate
using that variable in a subsequent command.
A. Type the following command.
invoke-command -session $session2 -scriptblock {$date = get-date displayhint time}

B. Type the following command to use the variable created in Step 10 A.


invoke-command -session $session2 -scriptblock {$date}
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 347 of 361

11. Type the following command to remove all sessions.


get-pssession | remove-pssession

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 348 of 361

Exercise 6: Create an Interactive Session with a


Remote Machine
Objectives
In this exercise, you will:

Create and use an interactive PowerShell remoting session

Scenario
The last type of remote session is an interactive remote session. The Enter-PSSession
Cmdlet automatically creates a remote session object and allows you to enter commands
as if you were physically sitting in front of the PowerShell console of the remote
computer. The Exit-PSSession Cmdlet takes you out of the remote interactive session.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


To open an elevated Windows PowerShell session:
1. Right-click the

icon on the Windows task bar.

2. Select Run As Administrator.


3. Click Yes if a User Account Control Prompt appears.
The PowerShell window will open.

Task 1: Create and use an interactive PowerShell remoting session


1. Type the following command to create an interactive session with the syddc01
machine.
enter-pssession -computername syddc01

Note: The prompt changes to [syddc01]: PS c:\users\administrator\documents>

2. Type the following commands to confirm the computer name. Note that using this
session is just like being at the console of the syddc01 machine.
$envvar = $env:computername

$envvar

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 349 of 361

3. Type the following command to close the session.


exit-pssession

4. Type the following command to remove all sessions.


get-pssession | remove-pssession

Task 1: Enter an Existing Persistent Session for Interactive Access


1. Type the following command to create a reference to a session.
$mysession = new-pssession -computername syddc01

2. Type the following command to enter the session using an existing session reference.
enter-pssession session $mysession

3. Type the following commands to confirm the computer name. Note that using this
session is just like being at the console of the syddc01 machine.
$envvar = $env:computername

$envvar

4. Type the following command to close the session.


exit-pssession

5. Type the following command to remove all sessions.


get-pssession | remove-pssession

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 350 of 361

Exercise 7: Create a Session Configuration


Objectives
In this lesson, you will:

Create and use a session configuration

Scenario
A very useful advanced feature of remote sessions is the ability to create constrained
configuration environments to which remote users can connect.
The Register-PSSessionConfiguration cmdlet is run on a local machine to create a new
configuration name with a number of configuration options.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


To open an elevated Windows PowerShell session:
1. Right-click the

icon on the Windows task bar.

2. Select Run As Administrator.


3. Click Yes if a User Account Control Prompt appears.
The PowerShell window will open.

Task 1: Create a New Customized Session Configuration


1. Type the following command to view the configured sessions on this machine.
get-pssessionconfiguration | format-list -property name, permission

2. Type the following command


get-variable

Note: The PSSessionConfigurationName variable value. This is the default


configuration for the machine. The default configuration is:
http://schemas.microsoft.com/powershell/Microsoft.PowerShell

3. A configuration script file is required. Type the following command to display an


example of such a script.
type $home\documents\remoteadmin_startupscript.ps1

The contents of the file are shown below:


Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 351 of 361

# Create a list of cmdlets you want to be available in this configuration:


$arrcmdlets = @("get-command","get-service","get-process")
# Set private visibility for all other cmdlets:
get-command | where-object {$arrcmdlets -notcontains $_.Name} | foreachobject{ $_.Visibility = "Private" }
# Turn off the users ability to use language statements:
$ExecutionContext.SessionState.LanguageMode="NoLanguage"

4. Type the following command.


Register-PSSessionConfiguration -Name RemoteAdmin -StartupScript
c:\users\administrator\documents\RemoteAdmin_StartupScript.ps1 MaximumReceivedDataSizePerCommandMB 20 -MaximumReceivedObjectSizeMB 2

5. Type Y to confirm the action and Y again to confirm restarting the WinRM service.
This command will create a new session configuration with the name.
RemoteAdmin. The script file from the previous step is specified as the
configuration source. The MaximumReceivedDataSizePerCommandMB
parameter limits the amount of data that can be sent to the machine in any single
remote command. The MaximumReceivedObjectSizeMB parameter limits the
amount of data that can be sent to the machine in any single object.
6. Type the following command again to view the configured sessions on this machine
now.
get-pssessionconfiguration | format-list -property name, permission

Note that permissions have not been configured for the new RemoteAdmin session
configuration.
7. Type the following command to configure permissions for the new RemoteAdmin
session configuration.
set-pssessionconfiguration remoteadmin showsecuritydescriptorui

8. Type Y to confirm the action.


9. Select the checkbox to Allow Execute/Invoke permissions for the Administrators
group.
Note: In a production environment, a more appropriate group will typically be
added and assigned permissions in this step.

10. Click Ok.


11. Type Y to confirm restarting the WinRM service.
12. Type the following command again to view the configured sessions on this machine
now.
get-pssessionconfiguration | format-list -property name, permission
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 352 of 361

Permissions have now been configured for the RemoteAdmin session configuration.

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


There are several different ways to open windows PowerShell. Each of these has its own
purpose. The first one we will use is most likely the simplest.
On the windows task bar locate the

icon.

This is the PowerShell icon. Right-Click on this icon, select Run As Administrator and
click Yes if a User Account Control prompt is presented. The PowerShell window will
open.
You will notice it looks quite different to the standard command prompt. It should have a
blue background and white text. It will also have the text
PS c:\users\administrator>
The PS also tells you that you are using a PowerShell shell and not the CMD Shell.

Task 2: Use the New Customized Session Configuration


1. Type the following command to create a new remote session that uses the new
RemoteAdmin configuration to the SYDDC01 machine.
$s = new-pssession -computername SYDDC01 -configurationname remoteadmin

2. Type the following command to return a list of all the available commands.
invoke-command -session $s -scriptblock {get-command}

Note: Only three commands (Get-Command, Get-Process and Get-Service)


specified in the script file remoteadmin_startupscript.ps1 are available.

3. Type the following command to test use of language elements (DoWhile).


invoke-command -session $s -scriptblock {$i=0;do {get-process} while ($i -eq
0)}

Note that this command fails as expected. The statement:


$ExecutionContext.SessionState.LanguageMode="NoLanguage" in the
remoteadmin_startupscript.ps1 disables use of language elements.
4. Type the following command to test using pipeline filtering and formatting
commands.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 353 of 361

invoke-command -session $s -scriptblock {get-process} |where-object {$_.handle


-gt 1000} | select-object name,handles,pscomputername

Note that these still work, even though the associated Cmdlets have been disabled.
5. Type the following command to remove all sessions from the machine.
get-pssession | remove-pssession

Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username: Contoso\Administrator

Password: P@ssword

Open Elevated Windows PowerShell Session


There are several different ways to open windows PowerShell. Each of these has its own
purpose. The first one we will use is most likely the simplest.
On the windows task bar locate the

icon.

This is the PowerShell icon. Right-Click on this icon, select Run As Administrator and
click Yes if a User Account Control prompt is presented. The PowerShell window will
open.
You will notice it looks quite different to the standard command prompt. It should have a
blue background and white text. It will also have the text
PS c:\users\administrator>
The PS also tells you that you are using a PowerShell shell and not the CMD Shell.

Task 3: Remove a Customized Session Configuration


1. Type the following command to remove the RemoteAdmin session configuration
from the machine.
unregister-pssessionconfiguration remoteadmin

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 354 of 361

Lesson 11 Hands-On : Remoting


Objectives
After completing this lab you will be able to:

Use PowerShell remoting to execute commands remotely

Use background jobs with remote tasks

Create a customized session configuration for PowerShell remoting

Prerequisites
The lab requires a Windows 7 client running in a domain environment.

Estimated time to complete this lab


30 minutes

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 355 of 361

Exercise 1: Execute Remote Commands


Objectives
In this exercise, you will:

Execute commands on remote machines using single remote commands.

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Task 2: Open Windows PowerShell Session


To open Windows PowerShell:
Click the

icon on the Windows task bar

Task 3: Enable PSremote


1. In the PowerShell console, type the following command to enable PSremoting
Enable-psremoting

2. Answer Y when prompted to continue.


You will notice that WinRM has already been enabled on the virtual machine.
3. Type the following command to run ipconfig on the machines.
Invoke-command computername syddc01,w7client scriptblock {ipconfig}

This will return the ipconfig information from both machines.


4. Type the following command to get details of the lsass process.
invoke-command -computername syddc01,w7client -scriptblock {get-process -name
lsass}

You will see an extra column (PSComputerName), as the information is coming


from invoke-command.
5. Type the following command to get the computer system information from WMI
Invoke-command computername syddc01,w7client scriptblock {get-wmiobject
win32_computersystem}

6. Type the following command to create a PSCredential object


$Credentials = Get-Credential

Enter the following details:

Microsoft | Services

Username; contoso\administrator
2012 Microsoft Corporation
Microsoft Confidential

ITOE Educate

Page 356 of 361

Password: P@ssword

7. Type the following command to use the credentials with invoke-command


Invoke-command computername syddc01 credential $Credentials scriptblock
{get-process}

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 357 of 361

Exercise 2: Execute Commands via Sessions


Objectives
In this exercise, you will:

Read the registry values of a remote machine for internet explorer details

Create a remote reg key and create values

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Task 2: Open Windows PowerShell Session


To open Windows PowerShell:
Click the

icon on the Windows task bar

Task 3: Create Remoting Sessions


1. In the PowerShell console, type the following command to create reusable sessions.
$mysessions = New-pssession computername syddc01,w7client

2. Type the following command to view the sessions


$mysessions

3. Type the following command to execute commands using the session


Invoke-Command -Session $mysessions -command {$env:computername}

The above command will return the computername of the computers. Since this is a
reusable session, you can create remote variables.
4. Type the following command to create a remote variable
Invoke-command session $mysessions scriptblock {$lastboot = (get-eventlog
logname system | where-object {$_.eventid eq 6005} | select-object first 1
property timegenerated).timegenerated}

5. Type the following command to view the remote variables.


Invoke-command -session $mysessions -scriptblock {"$env:computername :
$lastboot"}

6. Type the following command to create more remote variables.


Invoke-command session $mysessions scriptblock {$intevents =
20;$winrmlog=Microsoft-Windows-WinRM/Operational}

7. Type the following command to read events from the WinRM eventlog.
Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 358 of 361

Invoke-command session $mysessions scriptblock {get-winevent logname


$winrmlog maxevents $intevents}

8. Type the following command to get the w7client session.


Get-PSSession | where {$_.computername -like "w7client"}

You will now see the details for the psession on w7client. Note that is currently open.
9. Type the following command to remove the session.
Get-PSSession | where {$_.computername -like "w7client"} | Remove-PSSession

10. Type the following command to view the details of the $mysessions variable.
$mysessions

You will now see the details for both sessions. Note that because you removed the
session for w7client, it is now displayed as closed with availability as none.
11. Type the following command to use the sessions.
Invoke-command -session $mysessions -scriptblock {"$env:computername :
$lastboot"}

You will now receive an error from w7client as the session is closed. The session is
still available for syddc01 and you will receive a result from that machine.
12. Type the following to separate the sessions.
$activesessions = Get-PSSession | where {$_.state eq Opened and
$_.availability eq Available}

13. Type the following to ensure you have an active session.


$activesessions

14. Type the following command to test the active sessions.


Invoke-command -session $activesessions -scriptblock {"$env:computername :
$lastboot"}

This will now run without errors as only active sessions are stored in the
$activesessions variable.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 359 of 361

Exercise 3: Interactive Remote Console


Objectives
In this exercise, you will:

Read the permissions on a folder

Set the permissions on a folder

Task 1: Log on to the VM environment


Log on to Windows 7 Enterprise client.

Username; Contoso\Administrator

Password: P@ssword

Task 2: Open Windows PowerShell Session


To open Windows PowerShell:
Click the

icon on the Windows task bar

Task 3: Create a share on remote machine


1. In the PowerShell console, type the following command to list the shares available on
syddc01.
Get-wmiobject win32_share -computer syddc01

Note the list of shares. There is no software share currently.


2. Type the following command to test the share.
Test-path \\syddc01\software

You will get a false result as the share does not currently exist.
3. In the PowerShell console, type the following.
Enter-pssession syddc01

This will now enter an interactive remote console on syddc01. Note that the prompt
has changed to [syddc01]: PS C:\Users\Administrator\Documents>
This indicates that the console is now operating on syddc01.
4. In the console, type the following command to change location.
Set-location c:\shares

5. Type the following command to create a new directory.


New-item name software type directory

This will create a directory on the syddc01 server.


Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Page 360 of 361

6. Type the following command to create an instance of the WMI class.


$wmiclass = [wmiclass]win32_share

The line above creates an instance of the class win32_share with the wmiclass type
alias.
This is required as using get-wmiobject will not expose the create method.
7. Type the following command to create a new share on the server.
$wmiclass.Create("C:\shares\software","software",0)

The command above creates the share. The first part of the create method call is the
share path, the second part is the name of the share and the third part is the type of
share.
Note: A type 0 is a disk share.

8. Type the following command to exit the remote session.


Exit-pssession

You will notice that the prompt now returns to PS C:\Users\administrator>


indicating that you are now working on the local machine.
9. Type the following command to list the shares on syddc01.
Get-wmiobject win32_share -computer syddc01

You will notice that there is now a software share.


10. In the PowerShell console, type the following command to test the share.
Test-path \\syddc01\software

You will now get a true result as the share now exists.

Microsoft | Services

2012 Microsoft Corporation


Microsoft Confidential

ITOE Educate

Você também pode gostar