Windows PowerShell™ Primer
Microsoft Corporation
Published: September 2006
Primary Author: Alex Angelopoulos, MVP
Contributing Authors: Dean Tsaltas, June Blender 
Editors: Ron Loi, Craig Liebendorfer
Abstract
Windows PowerShell™ is a new Windows command-line shell designed especially for system administrators. The shell includes an interactive prompt and a scripting environment that can be used independently or in combination. 
This document describes the basic concepts and features of Windows PowerShell and suggests ways that you can use Windows PowerShell in system administration. 

Contents
Windows PowerShell Primer Copyright	7
Windows PowerShell Introduction	7
Audience	7
About Windows PowerShell	8
Discoverability	8
Consistency	8
Interactive and Scripting Environments	8
Object Orientation	9
Easy Transition to Scripting	9
Installing and Running Windows PowerShell	9
Installation Requirements	9
Installing Windows PowerShell	9
Running Windows PowerShell	10
Windows PowerShell Basics	10
Understanding Important Windows PowerShell Concepts	11
Commands are not Text-based	11
The Command Family is Extensible	11
Windows PowerShell Handles Console Input and Display	12
Windows PowerShell Uses Some C# Syntax	13
Learning Windows PowerShell Names	13
Cmdlets Use Verb-Noun Names to Reduce Command Memorization	14
Cmdlets Use Standard Parameters	15
The Help Parameter (?)	16
Common Parameters	16
Suggested Parameters	16
Getting Summary Command Information	16
Displaying available command types	17
Getting Detailed Help Information	18
Using Familiar Command Names	19
Interpreting Standard Aliases	20
Creating New Aliases	20
Using Tab Expansion to Automatically Complete Names	21
Object Pipeline	22
Understanding the Windows PowerShell Pipeline	22
Viewing Object Structure (Get-Member)	24
Using Format Commands to Change Output View	26
Using Format-Wide for Single-Item Output	27
Controlling Format-Wide Display with Column	27
Using Format-List for a List View	27
Getting Detailed Information by using Format-List with Wildcards	28
Using Format-Table for Tabular Output	28
Improving Format-Table Output (AutoSize)	29
Wrapping Format-Table Output in Columns (Wrap)	30
Organizing Table Output (-GroupBy)	31
Redirecting Data with Out-* Cmdlets	32
Paging Console Output (Out-Host)	33
Discarding Output (Out-Null)	34
Printing Data (Out-Printer)	34
Saving Data (Out-File)	34
Windows PowerShell Navigation	35
Managing the Current Location in Windows Powershell	36
Getting Your Current Location (Get-Location)	36
Setting Your Current Location (Set-Location)	36
Saving and Recalling Recent Locations (Push-Location and Pop-Location)	38
Managing Windows PowerShell Drives	39
Adding New Windows PowerShell Drives (New-PSDrive)	41
Deleting Windows PowerShell Drives (Remove-PSDrive)	43
Adding and Removing Drives Outside Windows PowerShell	43
Working With Files, Folders and Registry Keys	43
Enumerating Files, Folders, and Registry Keys (Get-ChildItem)	44
Listing all Contained Items (-Recurse)	44
Filtering Items by Name (-Name)	45
Forcibly Listing Hidden Items (-Force)	45
Matching Item Names with Wildcards	45
Excluding Items (-Exclude)	46
Mixing Get-ChildItem Parameters	47
Manipulating Items Directly	48
Creating New Items (New-Item)	48
Why Registry Values are not Items	49
Renaming Existing Items (Rename-Item)	50
Moving Items (Move-Item)	50
Copying Items (Copy-Item)	51
Deleting Items (Remove-Item)	51
Executing Items (Invoke-Item)	52
Working with Objects	52
Getting WMI Objects (Get-WmiObject)	53
Getting WMI Objects (Get-WmiObject)	53
Listing WMI Classes	53
Displaying WMI Class Details	54
Displaying Non-Default Properties with Format Cmdlets	56
Creating .NET and COM Objects (New-Object)	56
Using New-Object for Event Log Access	57
Using Constructors with New-Object	57
Storing Objects in Variables	58
Accessing a Remote Event Log with New-Object	58
Clearing an Event Log with Object Methods	58
Creating COM Objects with New-Object	60
Creating a Desktop Shortcut with WScript.Shell	60
Using Internet Explorer from Windows PowerShell	62
Getting Warnings about .NET-Wrapped COM Objects	63
Using Static Classes and Methods	64
Getting Environment Data with System.Environment	64
Referring to the Static System.Environment Class	65
Displaying Static Properties of System.Environment	66
Doing Math with System.Math	67
Removing Objects from the Pipeline (Where-Object)	69
Performing Simple Tests with Where-Object	69
Filtering Based on Object Properties	70
Repeating a Task for Multiple Objects (ForEach-Object)	72
Selecting Parts of Objects (Select-Object)	73
Sorting Objects	74
Using Variables to Store Objects	75
Creating a Variable	75
Manipulating Variables	76
Using Cmd.exe Variables	77
Using Windows PowerShell for Administration	77
Managing Local Processes	78
Listing Processes (Get-Process)	78
Stopping Processes (Stop-Process)	79
Stopping All Other Windows PowerShell Sessions	80
Managing Local Services	81
Listing Services	81
Stopping, Starting, Suspending, and Restarting Services	82
Collecting Information About Computers	83
Listing Desktop Settings	83
Listing BIOS Information	84
Listing Processor Information	84
Listing Computer Manufacturer and Model	84
Listing Installed Hotfixes	84
Listing Operating System Version Information	86
Listing Local Users and Owner	86
Getting Available Disk Space	86
Getting Logon Session Information	87
Getting the User Logged on to a Computer	87
Getting Local Time from a Computer	87
Displaying Service Status	88
Working with Software Installations	88
Listing Windows Installer Applications	89
Listing All Uninstallable Applications	91
Installing Applications	92
Removing Applications	92
Upgrading Windows Installer Applications	93
Changing Computer State: Locking, Logging Off, Shutting Down, and Rebooting	93
Locking a Computer	93
Logging Off the Current Session	94
Shutting Down or Rebooting a Computer	94
Working with Printers	95
Listing Printer Connections	95
Adding a Network Printer	95
Setting a Default Printer	95
Removing a Printer Connection	95
Performing Networking Tasks	96
Listing IP Addresses for a Computer	96
Listing IP Configuration Data	96
Pinging Computers	97
Retrieving Network Adapter Properties	98
Assigning the DNS Domain for a Network Adapter	98
Performing DHCP Configuration Tasks	99
Determining DHCP-Enabled Adapters	99
Retrieving DHCP Properties	99
Enabling DHCP on Each Adapter	99
Releasing and Renewing DHCP Leases on Specific Adapters	99
Releasing and Renewing DHCP Leases on All Adapters	100
Creating a Network Share	100
Removing a Network Share	101
Connecting a Windows Accessible Network Drive	101
Working with Files and Folders	101
Listing All the Files and Folders Within a Folder	101
Copying Files and Folders	102
Creating Files and Folders	102
Removing All Files and Folders Within a Folder	103
Mapping a Local Folder as a Windows Accessible Drive	103
Reading a Text File into an Array	103
Working with Registry Keys	104
Listing All Subkeys of a Registry Key	104
Copying Keys	105
Creating Keys	106
Deleting Keys	106
Removing All Keys Under a Specific Key	106
Working with Registry Entries	107
Listing Registry Entries	107
Getting a Single Registry Entry	109
Creating New Registry Entries	110
Renaming Registry Entries	111
Deleting Registry Entries	111
Appendix 1 - Compatibility Aliases	111
Appendix 2 - Creating a Custom PowerShell Shortcut	112

Windows PowerShell Primer Copyright
This document is provided for informational purposes only and Microsoft makes no warranties, either express or implied, in this document.  Information in this document, including URL and other Internet Web site references, is subject to change without notice.  The entire risk of the use or the results from the use of this document remains with the user.  Unless otherwise noted, the example 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.  Complying with all applicable copyright laws is the responsibility of the user.  Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document.  Except as expressly provided in any written license agreement from Microsoft; the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
© 2007 Microsoft Corporation.  All rights reserved.
Microsoft, MS-DOS, Windows, Windows NT, Windows 2000, Windows XP, and Windows Server 2003, are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
The names of actual companies and products mentioned herein may be the trademarks of their respective owners.
Windows PowerShell Introduction
Windows PowerShell is a command-line shell and scripting environment that brings the power of the .NET Framework to command-line users and script writers. It introduces a number of powerful new concepts that enables you to extend the knowledge you have gained and the scripts you have created within the Windows Command Prompt and Windows Script Host environments.
Audience
The Windows PowerShell Primer is intended for IT professionals, programmers, and power users who have no prior background with Windows PowerShell. Although a background in scripting and WMI are helpful, they are not assumed or required to understand this document.
About Windows PowerShell
Windows PowerShell is designed to improve the command-line and scripting environment by eliminating long-standing problems and adding new features.
Discoverability
Windows Powershell makes it easy to discover its features. For example, to find a list of cmdlets that view and change Windows services, type:
get-command *-service
After discovering which cmdlet accomplishes a task, you can learn more about the cmdlet by using the Get-Help cmdlet. For example, to display help about the Get-Service cmdlet, type:
get-help get-service
To fully understand the output of that cmdlet, pipe its output to the Get-Member cmdlet. For example, the following command displays information about the members of the object output by the Get-Service cmdlet.
get-service | get-member
Consistency
Managing systems can be a complex endeavor and tools that have a consistent interface help to control the inherent complexity. Unfortunately, neither command-line tools nor scriptable COM objects have been known for their consistency.
The consistency of Windows PowerShell is one of its primary assets. For example, if you learn how to use the Sort-Object cmdlet, you can use that knowledge to sort the output of any cmdlet. You do not have to learn the different sorting routines of each cmdlet. 
In addition, cmdlet developers do not have to design sorting features for their cmdlets. Windows PowerShell gives them a framework that provides the basic features and forces them to be consistent about many aspects of the interface. The framework eliminates some of the choices that are typically left to the developer, but, in return, it makes the development of robust and easy-to-use cmdlets much simpler.
Interactive and Scripting Environments
Windows PowerShell is a combined interactive and scripting environment that gives you access to command-line tools and COM objects, and also enables you to use the power of the .NET Framework Class Library (FCL).
This environment improves upon the Windows Command Prompt, which provides an interactive environment with multiple command-line tools. It also improves upon Windows Script Host (WSH) scripts, which let you use multiple command-line tools and COM automation objects, but do not provide an interactive environment.
By combining access to all of these features, Windows PowerShell extends the ability of the interactive user and the script writer, and makes system administration more manageable.
Object Orientation
Although you interact with Windows PowerShell by typing commands in text, Windows PowerShell is based on objects, not text. The output of a command is an object. You can send the output object to another command as its input. As a result, Windows PowerShell provides a familiar interface to people experienced with other shells, while introducing a new and powerful command-line paradigm. It extends the concept of sending data between commands by enabling you to send objects, rather than text.
Easy Transition to Scripting
Windows PowerShell makes it easy to transition from typing commands interactively to creating and running scripts. You can type commands at the Windows PowerShell command prompt to discover the commands that perform a task. Then, you can save those commands in a transcript or a history before copying them to a file for use as a script.
Installing and Running Windows PowerShell
Installation Requirements
Before you install Windows PowerShell, be sure that your system has the software programs that Windows PowerShell requires. Windows PowerShell requires the following programs:
·	Windows XP Service Pack 2, Windows 2003 Service Pack 1, or later versions of Windows
·	Microsoft .NET Framework 2.0
If any version of Windows PowerShell is already installed on the computer, use Add or Remove Programs in Control Panel to uninstall it before installing a new version. 
Installing Windows PowerShell
To install Windows PowerShell:
1.	Download the Windows PowerShell installation file. (The name of the file will differ with the platform, operating system, and language pack.)
2.	To start the installation, click Open.
3.	Follow the instructions on the installation wizard pages.

You can also save the Windows PowerShell files to a network share for installation on multiple computers.
To perform a silent installation, type:
<PowerShell-exe-file-name> /quiet
For example,
PowerShellSetup_x86_fre.exe /quiet

On 32-bit versions of Windows, Windows PowerShell is installed, by default, in the %SystemRoot%\System32\WindowsPowerShell\v1.0  directory. On 64-bit versions of Windows, a 32-bit version of Windows PowerShell is installed in the %SystemRoot%\SystemWow64\WindowsPowerShell\v1.0 directory and a 64-bit version of Windows PowerShell is installed in the %SystemRoot%\System32\WindowsPowerShell\v1.0 directory.
Running Windows PowerShell
To start Windows PowerShell from the Start Menu, click Start, click All Programs, click Windows PowerShell 1.0, and then click the Windows PowerShell icon.
To start Windows PowerShell from the Run box, click Start, click Run, type powershell, and click OK.
To start Windows PowerShell from a Command Prompt (cmd.exe) window, at the command prompt, type powershell. Because Windows PowerShell runs in a console session, you can use this same technique to run it within a remote telnet or SSH session. To return to your Command Prompt session, type exit.
Windows PowerShell Basics
Graphical interfaces use some basic concepts that are well known to most computer users. Users rely on the familiarity of those interfaces to to accomplish tasks. Operating systems present users with a graphical representation of items that can be browsed, usually with drop-down menus for accessing specific functionality and context menus for accessing context-specific functionality.
A command-line interface (CLI), such as Windows PowerShell, must use a different approach to expose information, because it does not have menus or graphical systems to help the user. You need to know command names before you can use them. Although you can type complex commands that are equivalent to the features in a GUI environment, you must become familiar with commonly-used commands and command parameters.
Most CLIs do not have patterns that can help the user to learn the interface. Because CLIs were the first operating system shells, many command names and parameter names were selected arbitrarily. Terse command names were generally chosen over clear ones. Although help systems and command design standards are integrated into most CLIs, they have been generally designed for compatibility with the earliest commands, so the command set is still shaped by decisions made decades ago.
Windows PowerShell was designed to take advantage of a user's historic knowledge of CLIs. In this chapter, we will talk about some basic tools and concepts that you can use to learn Windows PowerShell quickly. They include: 
·	Using Get-Command
·	Using Cmd.exe and UNIX commands
·	Using External Commands
·	Using Tab-Completion
·	Using Get-Help
Understanding Important Windows PowerShell Concepts
The Windows PowerShell design integrates concepts from many different environments. Several of them are familiar to people with experience in specific shells or programming environments, but very few people will know about all of them. Looking at some of these concepts provides a useful overview of the shell. 
Commands are not Text-based
Unlike traditional command-line interface commands, Windows PowerShell cmdlets are designed to deal with objects - structured information that is more than just a string of characters appearing on the screen. Command output always carries along extra information that you can use if you need it. We will discuss this topic in depth in this document. 
If you have used text-processing tools to process command-line data in the past, you will find that they behave differently if you try to use them in Windows PowerShell. In most cases, you do not need text-processing tools to extract specific information. You can access portions of the data directly by using standard Windows PowerShell object manipulation commands.
The Command Family is Extensible
Interfaces such as Cmd.exe do not provide a way for you to directly extend the built-in command set. You can create external command-line tools that run in Cmd.exe, but these external tools do not have services, such as help integration, and Cmd.exe does not automatically know that they are valid commands.
The native binary commands in Windows PowerShell, known as cmdlets (pronounced command-lets), can be augmented by cmdlets that you create and that you add to Windows PowerShell by using snap-ins. Windows PowerShell snap-ins are compiled, just like binary tools in any other interface. You can use them to add Windows PowerShell providers to the shell, as well as new cmdlets.
Because of the special nature of the Windows PowerShell internal commands, we will refer to them as cmdlets.
Note: 
Windows PowerShell can run commands other than cmdlets. We will not be discussing them in detail in the Windows PowerShell Primer, but they are useful to know about as categories of command types. Windows PowerShell supports scripts that are analogous to UNIX shell scripts and Cmd.exe batch files, but have a .ps1 file name extension. Windows PowerShell also allows you to create internal functions that can be used directly in the interface or in scripts.
Windows PowerShell Handles Console Input and Display
When you type a command, Windows PowerShell always processes the command-line input directly. Windows PowerShell also formats the output that you see on the screen. This is significant because it reduces the work required of each cmdlet and ensures that you can always do things the same way regardless of which cmdlet you are using. One example of how this simplifies life for both tool developers and users is command-line help.
Traditional command-line tools have their own schemes for requesting and displaying help. Some command-line tools use /? to trigger the help display; others use -?, /H, or even //. Some will display help in a GUI window, rather than in the console display. Some complex tools, such as application updaters, unpack internal files before displaying their help. If you use the wrong parameter, the tool might ignore what you typed and begin performing a task automatically.
When you enter a command in Windows PowerShell, everything you enter is automatically parsed and pre-processed by Windows PowerShell. If you use the -? parameter with a Windows PowerShell cmdlet, it always means "show me help for this command". Cmdlet developers do not have to parse the command; they only need to provide the help text.
It is important to understand that the help features of Windows PowerShell are available even when you run traditional command-line tools in Windows PowerShell. Windows PowerShell processes the parameters and passes the results to the external tools.
Note: 
If you run an graphic application in Windows PowerShell, the window for the application opens. Windows PowerShell intervenes only when processing the command-line input you supply or the application output returned to the console window; it does not affect how the application works internally.
Windows PowerShell Uses Some C# Syntax
Windows PowerShell has syntax features and keywords that are very similar to those used in the C# programming language, because Windows PowerShell is based on the .NET framework. Learning Windows PowerShell will make it much easier to learn C#, if you are interested in the language. 
If you are not a C# programmer, this similarity is not important. However, if you are already familiar with C#, the similarities can make learning Windows PowerShell much easier.
Learning Windows PowerShell Names
Learning names of commands and command parameters is a significant time investment with most command-line interfaces. The issue is that there are very few patterns, so the only way to learn is by memorizing each command and each parameter that you need to use on a regular basis. 
When you work with a new command or parameter, you cannot generally use what you already know; you have to find and learn a new name. If you look at how interfaces grow from a small set of tools with incremental additions to functionality, it is easy to see why the structure is nonstandard. With command names in particular, this may sound logical since each command is a separate tool, but there is a better way to handle command names.
Most commands are built to manage elements of the operating system or applications, such as services or processes. The commands have a variety of names that may or may not fit into a family. For example, on Windows systems, you can use the net start and net stop commands to start and stop a service. There is another more generalized service control tool for Windows that has a completely different name, sc, that does not fit into the naming pattern for the net service commands. For process management, Windows has the tasklist command to list processes and the taskkill command to kill processes.
Commands that take parameters have irregular parameter specifications. You cannot use the net start command to start a service on a remote computer. The sc command  will start a service on a remote computer, but to specify the remote computer, you must prefix its name with a double backslash. For example, to start the spooler service on a remote computer named DC01, you would type sc \\DC01 start spooler. To list tasks running on DC01, you need to use the /S (for "system") parameter and supply the name DC01 without backslashes, like this: tasklist /S DC01.
Although there are important technical distinctions between a service and a process, they are both examples of manageable elements on a computer that have a well-defined life cycle. You may want to start or stop a service or process, or get a list of all currently running services or processes. In other words, although a service and a process are different things, the actions we perform on a service or a process are often conceptually the same. Furthermore, choices we may make to customize an action by specifying parameters may be conceptually similar as well. 
Windows PowerShell exploits these similarities to reduce the number of distinct names you need to know to understand and use cmdlets.
Cmdlets Use Verb-Noun Names to Reduce Command Memorization
Windows PowerShell uses a "verb-noun" naming system, where each cmdlet name consists of a standard verb hyphenated with a specific noun. Windows PowerShell verbs are not always English verbs, but they express specific actions in Windows PowerShell. Nouns are very much like nouns in any language, they describe specific types of objects that are important in system administration. It is easy to demonstrate how these two-part names reduce learning effort by looking at a few examples of verbs and nouns.
Nouns are less restricted, but they should always describe what a command acts upon. Windows PowerShell has commands such as Get-Process, Stop-Process, Get-Service, and Stop-Service.
In the case of two nouns and two verbs, consistency does not simplify learning that much. However, if you look at a standard set of 10 verbs and 10 nouns, you then have only 20 words to understand, but those words can be used to form 100 distinct command names. 
Frequently, you can recognize what a command does by reading its name, and it is usually apparent what name should be used for a new command. For example, a computer shutdown command might be Stop-Computer. A command that lists all computers on a network might be Get-Computer. The command that gets the system date is Get-Date.
You can list all commands that include a particular verb with the -Verb parameter for Get-Command (We will discuss Get-Command in detail in the next section). For example, to see all cmdlets that use the verb Get, type:
PS> Get-Command -Verb Get
CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Get-Acl                         Get-Acl [[-Path] <String[]>]...
Cmdlet          Get-Alias                       Get-Alias [[-Name] <String[]...
Cmdlet          Get-AuthenticodeSignature       Get-AuthenticodeSignature [-...
Cmdlet          Get-ChildItem                   Get-ChildItem [[-Path] <Stri...
...
The -Noun parameter is even more useful because it allows you to see a family of commands that affect the same type of object. For example, if you want to see which commands are available for managing services, type following command:
PS> Get-Command -Noun Service
CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Get-Service                     Get-Service [[-Name] <String...
Cmdlet          New-Service                     New-Service [-Name] <String>...
Cmdlet          Restart-Service                 Restart-Service [-Name] <Str...
Cmdlet          Resume-Service                  Resume-Service [-Name] <Stri...
Cmdlet          Set-Service                     Set-Service [-Name] <String>...
Cmdlet          Start-Service                   Start-Service [-Name] <Strin...
Cmdlet          Stop-Service                    Stop-Service [-Name] <String...
Cmdlet          Suspend-Service                 Suspend-Service [-Name] <Str... 
...
A command is not necessarily a cmdlet, just because it has a verb-noun naming scheme. One example of a native Windows PowerShell command that is not a cmdlet but has a verb-noun name, is the command for clearing a console window, Clear-Host. The Clear-Host command is actually an internal function, as you can see if you run Get-Command against it:
PS> Get-Command -Name Clear-Host

CommandType     Name                            Definition
-----------     ----                            ----------
Function        Clear-Host                      $spaceType = [System.Managem...
Cmdlets Use Standard Parameters
As noted earlier, commands used in traditional command-line interfaces do not generally have consistent parameter names. Sometimes parameters do not have names at all. When they do, they are often single-character or abbreviated words that can be typed rapidly but are not easily understood by new users. 
Unlike most other traditional command-line interfaces, Windows PowerShell processes parameters directly, and uses this direct access to the parameters along with developer guidance to standardize parameter names. Although this does not guarantee that every cmdlet will always conform to the standards, it does encourage it.
Note
·	Parameter names always have a '-' prepended to them when you use them, to allow Windows PowerShell to clearly identify them as parameters. In the Get-Command -Name Clear-Host example, the parameter's name is Name, but it is entered as -Name.
·	Here are some of the general characteristics of the standard parameter names and usages.
The Help Parameter (?)
When you specify the -? parameter to any cmdlet, the cmdlet is not executed. Instead, Windows PowerShell displays help for the cmdlet. 
Common Parameters
Windows PowerShell has several parameters known as common parameters. Because these parameters are controlled by the Windows PowerShell engine,  whenever they are implemented by a cmdlet, they will always behave the same way. The common parameters are WhatIf, Confirm, Verbose, Debug, Warn, ErrorAction, ErrorVariable, OutVariable, and OutBuffer.
Suggested Parameters
The Windows PowerShell core cmdlets use standard names for similar parameters. Although the use of parameter names is not enforced, there is explicit guidance for usage to encourage standardization.
For example, the guidance recommends naming a parameter that refers to a computer by name as ComputerName, rather than Server, Host, System, Node, or other common alternative words. Among the important suggested parameter names are Force, Exclude, Include, PassThru, Path, and CaseSensitive.
Getting Summary Command Information
The Windows PowerShell Get-Command cmdlet retrieves the names of all available commands. When you type Get-Command at a Windows PowerShell prompt, you will see output similar to the following:
PS> Get-Command
CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Add-Content                     Add-Content [-Path] <String[...
Cmdlet          Add-History                     Add-History [[-InputObject] ...
Cmdlet          Add-Member                      Add-Member [-MemberType] <PS...
... 
This output looks a lot like the Help output of Cmd.exe: a tabular summary of internal commands. In the extract of the Get-Command command output shown above, every command shown has a CommandType of Cmdlet. A Cmdlet is Windows PowerShell's intrinsic command type that corresponds roughly to the dir and cd commands of Cmd.exe and to built-ins in UNIX shells such as BASH. 
In the output of the Get-Command command, all of the definitions end with ellipses (...) to indicate that PowerShell cannot display all of the content in the available space. When Windows PowerShell displays output, it formats the output as text and then arranges it to make the data fit cleanly into a console window. We will talk about this later in the section on formatters.
The Get-Command cmdlet has a Syntax parameter that allows you to retrieve just the syntax of each cmdlet. Enter the Get-Command -Syntax command to display the full output:
PS> Get-Command -Syntax
Add-Content [-Path] <String[]> [-Value] <Object[]> [-PassThru] [-Filter <String>] [-Include <String[]>] [-Exclude <String[]>] [-Force] [Credential <PSCredential>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-ErrorVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm] [-Encoding <FileSystemCmdletProviderEncoding>]

Add-History [[-InputObject] <PSObject[]>] [-Passthru] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-ErrorVariable <String>] [-OutVariable <String>][-OutBuffer <Int32>]...
Displaying available command types
The Get-Command command does not list every command that is available in Windows PowerShell. Instead, the Get-Command command lists only the cmdlets in the Windows PowerShell session. Windows PowerShell actually supports several other types of commands. Aliases, functions, and scripts are also Windows PowerShell commands, although they are not discussed in detail in the Windows PowerShell Primer. External files that are executables, or have a registered file type handler, are also classified as commands. 
You can return a listing of all items that can be invoked by entering the following command:
PS> Get-Command *
Because this list includes external files in your search path, it may contain thousands of items. It is more useful to look at a reduced set of commands. To find native commands of other types, you can use the CommandType parameter of the Get-Command cmdlet. Although we have not talked about these other command types yet, you can still display them if you know the name of the CommandType for a class of commands. 
Note: 
Although we have not discussed it yet, the asterisk (*) is used for wildcard matching in Windows PowerShell command arguments. The * means "match one or more of any characters". You can type Get-Command a* to find all commands that begin with the letter "a". Unlike wildcard matching in Cmd.exe, Windows PowerShell's wildcard will also match a period. 
To display the special command category aliases (these are nicknames used as alternatives to standard command names), enter the following command:
PS> Get-Command -CommandType Alias
To display all Windows PowerShell functions, enter the following command:
PS> Get-Command -CommandType Function
To display external scripts in Windows PowerShell's search path, enter the following command:
PS> Get-Command -CommandType ExternalScript
Getting Detailed Help Information
Windows PowerShell has detailed help documentation for all cmdlets. To display the help topics, use the Get-Help cmdlet. For example, to get help for the Get-Childitem cmdlet, type:
get-help get-childitem
or
get-childitem -?
You can also display one page of each help topic at a time by using the man and help functions. To use them, type man or help followed by the cmdlet name. For example, to display help for the Get-Childitem cmdlet, type
man get-childitem
or
help get-childitem
The Get-Help cmdlet also displays information about conceptual topics in Windows PowerShell. Conceptual help topics begin with the "about_" prefix, such as about_line_editing. (The name of the conceptual topic must be entered in English even on non-English versions of Windows PowerShell.)
To display a list of conceptual topics, type:
get-help about_*
To display a particular help topic, type the topic name, for example:
get-help about_line_editing
Using Familiar Command Names
Using a mechanism called aliasing, Windows PowerShell allows users to refer to commands by alternate names. Aliasing allows users with experience in other shells to reuse common command names that they already know to perform similar operations in Windows PowerShell. Although we will not discuss Windows PowerShell aliases in detail, you can still use them as you get started with Windows PowerShell.
Aliasing associates a command name that you type with another command. For example, Windows PowerShell has an internal function named Clear-Host that clears the output window. If you type either the cls or clear command at a command prompt, Windows PowerShell interprets that this is an alias for the Clear-Host function and runs the Clear-Host function.
This feature helps users to learn Windows PowerShell. First, most Cmd.exe and UNIX users have a large repertoire of commands that users already know by name, and although the Windows PowerShell equivalents may not produce identical results, they are close enough in form that users can use them to do work without having to first memorize the Windows PowerShell names. Second, the major source of frustration in learning a new shell when the user is already familiar with another shell, is the errors that are caused by "finger memory". If you have used Cmd.exe for years, when you have a screen full of output and want to clean it up, you would reflexively type the cls command and press the ENTER key. Without the alias to the Clear-Host function in Windows PowerShell, you would simply get the error message "'cls' is not recognized as a cmdlet, function, operable program, or script file." and be left with no idea of what to do to clear the output.
The following is a brief listing of the common Cmd.exe and UNIX commands that you can use inside Windows PowerShell:

cat	dir	mount	rm	
cd	echo	move	rmdir	
chdir	erase	popd	sleep	
clear	h	ps	sort	
cls	history	pushd	tee	
copy	kill	pwd	type	
del	lp	r	write	
diff	ls	ren	 	

If you find yourself using one of these commands reflexively and want to learn the real name of the native Windows PowerShell command, you can use the Get-Alias command:
PS> Get-Alias cls

CommandType     Name                            Definition
-----------     ----                            ----------
Alias           cls                             Clear-Host
To make examples more readable, the Windows PowerShell Primer generally avoids using aliases. However, knowing more about aliases this early can still be useful if you are working with arbitrary snippets of Windows PowerShell code from another source or wish to define your own aliases. The rest of this section will discuss standard aliases and how to define your own aliases.
Interpreting Standard Aliases
Unlike the aliases described above, which were designed for name-compatibility with other interfaces, the aliases built into Windows PowerShell are generally designed for brevity. These shorter names can be typed quickly, but are impossible to read if you do not know what they refer to.
Windows PowerShell tries to compromise between clarity and brevity by providing a set of standard aliases that are based on shorthand names for common verbs and nouns. This allows a core set of aliases for common cmdlets that are readable once you know the shorthand names. For example, in standard aliases the verb Get is abbreviated to g, the verb Set is abbreviated to s, the noun Item is abbreviated to i, the noun Location is abbreviated to l, and the noun Command is abbreviated to cm.
Here is a brief example to illustrate how this works. The standard alias for Get-Item comes from combining g for Get and i for Item: gi. The standard alias for Set-Item comes from combining s for Set and i for Item: si. The standard alias for Get-Location comes from combining g for Get and l for Location, gl. The standard alias for Set-Location comes from combining s for Set and l for Location, sl. The standard alias for Get-Command comes from combining g for Get and cm for Command, gcm. There is no Set-Command cmdlet, but if there were, we would be able to guess that the standard alias comes from s for Set and cm for Command: scm. Furthermore, people familiar with Windows PowerShell aliasing who encounter scm would be able to guess that the alias refers to Set-Command.
Creating New Aliases
You can create your own aliases using the Set-Alias cmdlet. For example, the following statements create the standard cmdlet aliases discussed in Interpreting Standard Aliases:
Set-Alias -Name gi -Value Get-Item
Set-Alias -Name si -Value Set-Item
Set-Alias -Name gl -Value Get-Location
Set-Alias -Name sl -Value Set-Location
Set-Alias -Name gcm -Value Get-Command
Internally, Windows PowerShell uses commands like these during startup, but these aliases are not changeable. If you attempt to actually execute one of these commands, you will get an error explaining that the alias cannot be modified. For example:
PS> Set-Alias -Name gi -Value Get-Item
Set-Alias : Alias is not writeable because alias gi is read-only or constant and cannot be written to.
At line:1 char:10
+ Set-Alias  <<<< -Name gi -Value Get-Item
Using Tab Expansion to Automatically Complete Names
Command-line shells often provide a way to complete the names of long files or commands automatically, speeding up command entry and providing hints. Windows PowerShell allows you to fill in file names and cmdlet names by pressing the Tab key.
Note: 
Tab expansion is controlled by the internal function TabExpansion. Since this function can be modified or overridden, this discussion is a guide to the behavior of the default Windows PowerShell configuration.
To fill in a filename or path from the available choices automatically, type part of the name and press the Tab key. Windows PowerShell will automatically expand the name to the first match that it finds. Pressing the Tab key repeatedly will cycle through all of the available choices. 
The tab expansion of cmdlet names is slightly different. To use tab expansion on a cmdlet name, type the entire first part of the name (the verb)  and the hyphen that follows it. You can fill in more of the name for a partial match. For example, if you type get-co and then press the Tab key, Windows PowerShell will automatically expand this to the Get-Command cmdlet (notice that it also changes the case of letters to their standard form). If you press Tab key again, Windows PowerShell replaces this with the only other matching cmdlet name, Get-Content.
You can use tab expansion repeatedly on the same line. For example, you can use tab expansion on the name of the Get-Content cmdlet by entering:
PS> Get-Con<Tab>
When you press the Tab key, the command expands to:
PS> Get-Content
You can then partially specify the path to the Active Setup log file and use tab expansion again:
PS> Get-Content c:\windows\acts<Tab>
When you press the Tab key, the command expands to:
PS> Get-Content C:\windows\actsetup.log
Note: 
One limitation of the tab expansion process is that tabs are always interpreted as attempts to complete a word. If you copy and paste command examples into a Windows PowerShell console, make sure that the sample does not contain tabs; if it does, the results will be unpredictable and will almost certainly not be what you intended.
Object Pipeline

 Pipelines act like a series of connected segments of pipe. Items moving along the pipeline pass through each segment. To create a pipeline in Windows PowerShell, you connect commands together with the pipe operator "|" and the output of each command is used as input to the next command.
Pipelines are arguably the most valuable concept used in command-line interfaces. Properly used, pipelines not only reduce the effort involved in entering complex commands, but also make it easier to see the flow of work in the commands. A related useful characteristic of pipelines is that since they operate on each item separately, you do not have to modify them based on whether you will have zero, one, or many items in the pipeline. Furthermore, each command in a pipeline (called a pipeline element) usually passes its output to the next command in the pipeline item-by-item. This usually reduces the resource demand of complex commands and allows you to begin getting the output immediately.
In this chapter, we will describe how the Windows PowerShell pipeline differs from the pipelines of most popular shells, and then demonstrate some basic tools that you can use to help control pipeline output and also to see how the pipeline operates.
Understanding the Windows PowerShell Pipeline
Piping works virtually everywhere in Windows PowerShell. Although you see text on the screen, Windows PowerShell does not pipe text between commands. Instead, it pipes objects. 
The notation used for pipelines is similar to that used in other shells, so at first glance, it may not be apparent that Windows PowerShell introduces something new. For example, if you use the Out-Host cmdlet to force a page-by-page display of output from another command, the output looks just like the normal text displayed on the screen, broken up into pages:
PS> Get-ChildItem -Path C:\WINDOWS\System32 | Out-Host -Paging
    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\WINDOWS\system32

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005-10-22  11:04 PM        315 $winnt$.inf
-a---        2004-08-04   8:00 AM      68608 access.cpl
-a---        2004-08-04   8:00 AM      64512 acctres.dll
-a---        2004-08-04   8:00 AM     183808 accwiz.exe
-a---        2004-08-04   8:00 AM      61952 acelpdec.ax
-a---        2004-08-04   8:00 AM     129536 acledit.dll
-a---        2004-08-04   8:00 AM     114688 aclui.dll
-a---        2004-08-04   8:00 AM     194048 activeds.dll
-a---        2004-08-04   8:00 AM     111104 activeds.tlb
-a---        2004-08-04   8:00 AM       4096 actmovie.exe
-a---        2004-08-04   8:00 AM     101888 actxprxy.dll
-a---        2003-02-21   6:50 PM     143150 admgmt.msc
-a---        2006-01-25   3:35 PM      53760 admparse.dll
<SPACE> next page; <CR> next line; Q quit
...
The Out-Host -Paging command is a useful pipeline element whenever you have lengthy output that you would like to display slowly .It is especially useful if the operation is very CPU-intensive. Since processing is transferred to the Out-Host cmdlet when it has a complete page ready to display, cmdlets that proceed it in the pipeline halt operation until the next page of output is available. You can see this if you use the Windows Task Manager to monitor CPU and memory use by Windows PowerShell. 
Run the following command: Get-ChildItem C:\Windows -Recurse. Compare the CPU and memory usage to this command: Get-ChildItem C:\Windows -Recurse | Out-Host -Paging. What you see on the screen is text, but that is because it is necessary to represent objects as text in a console window. This is really just a representation of what is really going on inside Windows PowerShell. For example, consider the Get-Location cmdlet. If you type Get-Location while your current location is the root of the C drive, you would see the following output:
PS> Get-Location

Path
----
C:\
If Windows PowerShell pipelined text, issuing a command such as Get-Location | Out-Host, would pass from Get-Location to Out-Host a set of characters in the order they are displayed onscreen. In other words, if you were to ignore the heading information, Out-Host would first receive the character 'C', then the character ':', then the character '\'. The Out-Host cmdlet could not determine what meaning to associate with the characters output by the Get-Location cmdlet.
Instead of using text to let commands in a pipeline communicate, Windows PowerShell uses objects. From the standpoint of a user, objects package related information into a form that makes it easier to manipulate the information as a unit, and extract specific items that you need. 
The Get-Location command does not return text that contains the current path. It returns a package of information called a PathInfo object that contains the current path along with some other information. The Out-Host cmdlet then sends this PathInfo object to the screen, and Windows PowerShell decides what information to display and how to display it based on its formatting rules.
In fact, the heading information output by the Get-Location cmdlet is added only at the end of the process, as part of the process of formatting the data for onscreen display. What you see onscreen is a summary of information, and not a complete representation of the output object.
Given that there may be more information output from a Windows PowerShell command than what we see displayed in the console window, how can you retrieve the non-visible elements? How do you view the extra data? And what if you want to view the data in a format different than the one Windows PowerShell normally uses?
The rest of this chapter discusses how you can discover the structure of specific Windows PowerShell objects, selecting specific items and formatting them for easier display, and how to send this information to alternative output locations such as files and printers.
Viewing Object Structure (Get-Member)
Because objects play such a central role in Windows PowerShell, there are several native commands designed to work with arbitrary object types. The most important one is the Get-Member command.
The simplest technique for analyzing the objects that a command returns is to pipe the output of that command to the Get-Member cmdlet. The Get-Member cmdlet shows you the formal name of the object type and a complete listing of its members. The number of elements that are returned can sometimes be overwhelming. For example, a process object can have over 100 members.
To see all of the members of a Process object and page the output so you can view all of it, type:  
PS> Get-Process | Get-Member | Out-Host -Paging
The output from this command will look something like this:
   TypeName: System.Diagnostics.Process

Name                           MemberType     Definition
----                           ----------     ----------
Handles                        AliasProperty  Handles = Handlecount
Name                           AliasProperty  Name = ProcessName
NPM                            AliasProperty  NPM = NonpagedSystemMemorySize
PM                             AliasProperty  PM = PagedMemorySize
VM                             AliasProperty  VM = VirtualMemorySize
WS                             AliasProperty  WS = WorkingSet
add_Disposed                   Method         System.Void add_Disposed(Event...
...
We can make this long list of information more usable by filtering for elements we want to see. The Get-Member command lets you list only members that are properties. There are several forms of properties. The cmdlet displays properties of any type if we set the Get-MemberMemberType parameter to the value Properties. The resulting list is still very long, but a bit more manageable:
PS> Get-Process | Get-Member -MemberType Properties

   TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName
...
ExitCode                   Property       System.Int32 ExitCode {get;}
...
Handle                     Property       System.IntPtr Handle {get;}
...
CPU                        ScriptProperty System.Object CPU {get=$this.Total...
...
Path                       ScriptProperty System.Object Path {get=$this.Main...
...
Note: 
The allowed values of MemberType are AliasProperty, CodeProperty, Property, NoteProperty, ScriptProperty, Properties, PropertySet, Method, CodeMethod, ScriptMethod, Methods, ParameterizedProperty, MemberSet, and All.
There are over 60 properties for a process. The reason Windows PowerShell often shows only a handful of properties for any well-known object is that showing all of them would produce an unmanageable amount of information.
Note: 
Windows PowerShell determines how to display an object type by using information stored in XML files that have names ending in .format.ps1xml. The formatting data for process objects, which are .NET System.Diagnostics.Process objects, is stored in PowerShellCore.format.ps1xml.
If you need to look at properties other than those that Windows PowerShell displays by default, you will need to format the output data yourself. This can be done by using the format cmdlets.
Using Format Commands to Change Output View
Windows PowerShell has a set of cmdlets that allow you to control which properties are displayed for particular objects. The names of all the cmdlets begin with the verb Format. They let you select one or more properties to show.
The Format cmdlets are Format-Wide, Format-List, Format-Table, and Format-Custom. We will only describe the Format-Wide, Format-List, and Format-Table cmdlets in this primer.
Each format cmdlet has default properties that will be used if you do not specify specific properties to display. Each cmdlet also uses the same parameter name, Property, to specify which properties you want to display. Because Format-Wide only shows a single property, its Property parameter only takes a single value, but the property parameters of Format-List and Format-Table will accept a list of property names.
If you use the command Get-Process -Name powershell with 2 instances of Windows PowerShell running, you get output that looks like this:
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    995       9    30308      27996   152     2.73   2760 powershell
    331       9    23284      29084   143     1.06   3448 powershell
In the rest of this section, we will explore how to use Format cmdlets to change the way the output of this command is displayed.
Using Format-Wide for Single-Item Output
The Format-Wide cmdlet, by default, displays only the default property of an object. The information associated with each object is displayed in a single column:
PS> Get-Process -Name powershell | Format-Wide

powershell                              powershell
You can also specify a non-default property:
PS> Get-Process -Name powershell | Format-Wide -Property Id

2760                                    3448
Controlling Format-Wide Display with Column
With the Format-Wide cmdlet, you can only display a single property at a time. This makes it useful for displaying simple lists that show only one element per line. To get a simple listing, set the value of the Column parameter to 1 by typing:
Get-Command Format-Wide -Property Name -Column 1
Using Format-List for a List View
The Format-List cmdlet displays an object in the form of a listing, with each property labeled and displayed on a separate line:
PS> Get-Process -Name powershell | Format-List

Id      : 2760
Handles : 1242
CPU     : 3.03125
Name    : powershell

Id      : 3448
Handles : 328
CPU     : 1.0625
Name    : powershell
You can specify as many properties as you want:
PS> Get-Process -Name powershell | Format-List -Property ProcessName,FileVersion
,StartTime,Id

ProcessName : powershell
FileVersion : 1.0.9567.1
StartTime   : 2006-05-24 13:42:00
Id          : 2760

ProcessName : powershell
FileVersion : 1.0.9567.1
StartTime   : 2006-05-24 13:54:28
Id          : 3448
Getting Detailed Information by using Format-List with Wildcards
The Format-List cmdlet lets you use a wildcard as the value of its Property parameter. This lets you display detailed information. Often, objects include more information than you need, which is why Windows PowerShell does not show all property values by default. To show all of properties of an object, use the Format-List -Property * command. The following command generates over 60 lines of output for a single process:
Get-Process -Name powershell | Format-List -Property *
Although the Format-List command is useful for showing detail, if you want an overview of output that includes many items, a simpler tabular view is often more useful.
Using Format-Table for Tabular Output
If you use the Format-Table cmdlet with no property names specified to format the output of the Get-Process command, you get exactly the same output as you do without performing any formatting. The reason is that processes are usually displayed in a tabular format, as are most Windows PowerShell objects.
PS> Get-Process -Name powershell | Format-Table

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1488       9    31568      29460   152     3.53   2760 powershell
    332       9    23140        632   141     1.06   3448 powershell
Improving Format-Table Output (AutoSize)
Although a tabular view is useful for displaying a lot of comparable information, it may be difficult to interpret if the display is too narrow for the data. For example, if you try to display process path, ID, name, and company, you get truncated output for the process path and the company column:
PS> Get-Process -Name powershell | Format-Table -Property Path,Name,Id,Company

Path                Name                                 Id Company
----                ----                                 -- -------
C:\Program Files... powershell                         2836 Microsoft Corpor...
If you specify the AutoSize parameter when you run the Format-Table command, Windows PowerShell will calculate column widths based on the actual data you are going to display. This makes the Path column readable, but the company column remains truncated:
PS> Get-Process -Name powershell | Format-Table -Property Path,Name,Id,Company -
AutoSize

Path                                                    Name         Id Company
----                                                    ----         -- -------
C:\Program Files\Windows PowerShell\v1.0\powershell.exe powershell 2836 Micr...
The Format-Table cmdlet might still truncate data, but it will only do so at the end of the screen. Properties, other than the last one displayed, are given as much size as they need for their longest data element to display correctly. You can see that company name is visible but path is truncated if you swap the locations of Path and Company in the Property value list:
PS> Get-Process -Name powershell | Format-Table -Property Company,Name,Id,Path -
AutoSize

Company               Name         Id Path
-------               ----         -- ----
Microsoft Corporation powershell 2836 C:\Program Files\Windows PowerShell\v1...
The Format-Table command assumes that the nearer a property is to the beginning of the property list, the more important it is. So it attempts to display the properties nearest the beginning completely. If the Format-Table command cannot display all of the properties, it will remove some columns from the display and provide a warning. You can see this behavior if you make Name the last property in the list:
PS> Get-Process -Name powershell | Format-Table -Property Company,Path,Id,Name -
AutoSize

WARNING: column "Name" does not fit into the display and was removed.

Company               Path                                                    I
                                                                              d
-------               ----                                                    -
Microsoft Corporation C:\Program Files\Windows PowerShell\v1.0\powershell.exe 6
In the output above, the ID column is truncated to make it fit into the listing, and the column headings are stacked up. Automatically resizing the columns does not always do what you want.
Wrapping Format-Table Output in Columns (Wrap)
You can force lengthy Format-Table data to wrap within its display column by using the Wrap parameter. Using the Wrap parameter alone will not necessarily do what you expect, since it uses default settings if you do not also specify AutoSize:
PS> Get-Process -Name powershell | Format-Table -Wrap -Property Name,Id,Company,
Path

Name                                 Id Company             Path
----                                 -- -------             ----
powershell                         2836 Microsoft Corporati C:\Program Files\Wi
                                        on                  ndows PowerShell\v1
                                                            .0\powershell.exe 
An advantage of using the Wrap parameter by itself is that it does not slow down processing very much. If you perform a recursive file listing of a large directory system, it might take a very long time and use a lot of memory before displaying the first output items if you use AutoSize.
If you are not concerned about system load, then AutoSize works well with the Wrap parameter. The initial columns are always allotted as much width as they need to display items on one line, just as when you specify AutoSize without the Wrap parameter. The only difference is that the final column will be wrapped if necessary:
PS> Get-Process -Name powershell | Format-Table -Wrap -AutoSize -Property Name,I
d,Company,Path

Name         Id Company               Path
----         -- -------               ----
powershell 2836 Microsoft Corporation C:\Program Files\Windows PowerShell\v1.0\
                                      powershell.exe
Some columns might not be displayed if you specify the widest columns first, so it is safest to specify the smallest data elements first. In the following example, we specify the extremely wide path element first, and even with wrapping, we still lose the final Name column:
 PS> Get-Process -Name powershell | Format-Table -Wrap -AutoSize -Property Path,I
d,Company,Name

WARNING: column "Name" does not fit into the display and was removed.

Path                                                      Id Company
----                                                      -- -------
C:\Program Files\Windows PowerShell\v1.0\powershell.exe 2836 Microsoft Corporat
                                                             ion
Organizing Table Output (-GroupBy)
Another useful parameter for tabular output control is GroupBy. Longer tabular listings in particular may be hard to compare. The GroupBy parameter groups output based on a property value. For example, we can group processes by company for easier inspection, omitting the company value from the property listing:
PS> Get-Process -Name powershell | Format-Table -Wrap -AutoSize -Property Name,I
d,Path -GroupBy Company

   Company: Microsoft Corporation

Name         Id Path
----         -- ----
powershell 1956 C:\Program Files\Windows PowerShell\v1.0\powershell.exe
powershell 2656 C:\Program Files\Windows PowerShell\v1.0\powershell.exe
Redirecting Data with Out-* Cmdlets
Windows PowerShell provides several cmdlets that let you control data output directly. These cmdlets share two important characteristics.
First, they generally transform data to some form of text. They do this because they output the data to system components that require text input. This means they need to represent the objects as text. Therefore, the text is formatted as you see it in the Windows PowerShell console window. 
Second, these cmdlets use the Windows PowerShell verb Out because they send information out from Windows PowerShell to somewhere else. The Out-Host cmdlet is no exception: the host window display is outside of Windows PowerShell. This is important because when data is sent out of Windows PowerShell, it is actually removed. You can see this if you try to create a pipeline that pages data to the host window, and then attempt to format it as a list, as shown here:
PS> Get-Process | Out-Host -Paging | Format-List
You might expect the command to display pages of process information in list format. Instead, it displays the default tabular list:
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    101       5     1076       3316    32     0.05   2888 alg
...
    618      18    39348      51108   143   211.20    740 explorer
    257       8     9752      16828    79     3.02   2560 explorer
...
<SPACE> next page; <CR> next line; Q quit
...
The Out-Host cmdlet sends the data directly to the console, so the Format-List command never receives anything to format.
The correct way to structure this command is to put the Out-Host cmdlet at the end of the pipeline as shown below. This causes the process data to be formatted in a list before being paged and displayed.
PS> Get-Process | Format-List | Out-Host -Paging

Id      : 2888
Handles : 101
CPU     : 0.046875
Name    : alg
...

Id      : 740
Handles : 612
CPU     : 211.703125
Name    : explorer

Id      : 2560
Handles : 257
CPU     : 3.015625
Name    : explorer
...
<SPACE> next page; <CR> next line; Q quit
...
This applies to all of the Out cmdlets. An Out cmdlet should always appear at the end of the pipeline.
Note: 
All the Out cmdlets render output as text, using the formatting in effect for the console window, including line length limits.
Paging Console Output (Out-Host)
By default, Windows PowerShell sends data to the host window, which is exactly what the Out-Host cmdlet does. The primary use for the Out-Host cmdlet is paging data as we discussed earlier. For example, the following command uses Out-Host to page the output of the Get-Command cmdlet:
PS> Get-Command | Out-Host -Paging
You can also use the more function to page data. In Windows PowerShell, more is a function that calls Out-Host -Paging. The following command demonstrates using the more function to page the output of Get-Command:
PS> Get-Command | more
If you include one or more filenames as arguments to the more function, the function will read the specified files and page their contents to the host:
PS> more c:\boot.ini
[boot loader]
timeout=5
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
...
Discarding Output (Out-Null)
The Out-Null cmdlet is designed to immediately discard any input it receives. This is useful for discarding unnecessary data that you get as a side-effect of running a command. When type the following command, you do not get anything back from the command:
PS> Get-Command | Out-Null
The Out-Null cmdlet does not discard error output. For example, if you enter the following command, a message is displayed informing you that Windows PowerShell does not recognize 'Is-NotACommand':
PS> Get-Command Is-NotACommand | Out-Null
Get-Command : 'Is-NotACommand' is not recognized as a cmdlet, function, operabl
e program, or script file.
At line:1 char:12
+ Get-Command  <<<< Is-NotACommand | Out-Null
Printing Data (Out-Printer)
You can print data by using the Out-Printer cmdlet. The Out-Printer cmdlet will use your default printer if you do not provide a printer name. You can use any Windows-based printer by specifying its display name. There is no need for any kind of printer port mapping or even a real physical printer. For example, if you have the Microsoft Office document imaging tools installed, you can send the data to an image file by typing:
PS> Get-Command Get-Command | Out-Printer -Name "Microsoft Office Document Image Writer"
Saving Data (Out-File)
You can send output to a file instead of the console window by using the Out-File cmdlet. The following command line sends a list of processes to the file C:\temp\processlist.txt:
PS> Get-Process | Out-File -FilePath C:\temp\processlist.txt 
The results of using the Out-File cmdlet may not be what you expect if you are used to traditional output redirection. To understand its behavior, you must be aware of the context in which the Out-File cmdlet operates.
By default, the Out-File cmdlet creates a Unicode file. This is the best default in the long run, but it means that tools that expect ASCII files will not work correctly with the default output format. You can change the default output format to ASCII by using the Encoding parameter:
PS> Get-Process | Out-File -FilePath C:\temp\processlist.txt -Encoding ASCII
Out-file formats file contents to look like console output. This causes the output to be truncated just as it is in a console window in most circumstances. For example, if you run the following command:
PS> Get-Command | Out-File -FilePath c:\temp\output.txt
The output will look like this:
CommandType     Name                            Definition                     
-----------     ----                            ----------                     
Cmdlet          Add-Content                     Add-Content [-Path] <String[...
Cmdlet          Add-History                     Add-History [[-InputObject] ...
...
To get output that does not force line wraps to match the screen width, you can use the Width parameter to specify line width. Because Width is a 32-bit integer parameter, the maximum value it can have is 2147483647. Type the following to set the line width to this maximum value:
Get-Command | Out-File -FilePath c:\temp\output.txt -Width 2147483647
The Out-File cmdlet is most useful when you want to save output as it would have displayed on the console. For finer control over output format, you need more advanced tools. We will look at those in the next chapter, along with some details about object manipulation.
Windows PowerShell Navigation
Folders are a familiar organizational feature of the Windows Explorer interface, Cmd.exe, and UNIX tools such as BASH. Folders, or directories as they are more commonly known, are a useful concept for organizing files and other directories. UNIX-family operating systems extend this by treating everything possible as a file; specific hardware and network connections appear as files within particular folders. This approach does not ensure that the content is readable or usable by particular applications, but it does make it simpler to find specific items. Tools that enumerate or search through files and folders work with these devices as well. You can also address a specific item by using the path to the file that represents it.
Analogously, the Windows PowerShell infrastructure supports exposing virtually anything that can be navigated like a standard Microsoft Windows disk drive or a UNIX filesystem as a Windows PowerShell Drive. A Windows PowerShell Drive does not necessarily represent a real drive, either locally or on the network. This chapter primarily discusses navigation for filesystems, but the concepts apply to Windows PowerShell Drives that are not associated with file systems.
Managing the Current Location in Windows Powershell
When navigating folder systems in Windows Explorer, you usually have a specific working location - namely, the current open folder. Items in the current folder can be manipulated easily by clicking them. For command-line interfaces such as Cmd.exe, when you are in the same folder as a particular file, you can access it by specifying a relatively short name, rather than needing to specify the entire path to the file. The current directory is called the working directory.
Windows PowerShell uses the noun Location to refer to the working directory, and implements a family of cmdlets to examine and manipulate your location.
Getting Your Current Location (Get-Location)
To determine the path of your current directory location, enter the Get-Location command:
PS> Get-Location
Path
----
C:\Documents and Settings\PowerUser
Note: 
The Get-Location cmdlet is similar to the pwd command in the BASH shell. The Set-Location cmdlet is similar to the cd command in Cmd.exe.
Setting Your Current Location (Set-Location)
The Get-Location command is used with the Set-Location command. The Set-Location command allows you to specify your current directory location.
PS> Set-Location -Path C:\Windows
After you enter the command, you will notice that you do not receive any direct feedback about the effect of the command. Most Windows PowerShell commands that perform an action produce little or no output because the output is not always useful. To verify that a successful directory change has occurred when you enter the Set-Location command, include the -PassThru parameter when you enter the Set-Location command:
PS> Set-Location -Path C:\Windows -PassThru
Path
----
C:\WINDOWS
The -PassThru parameter can be used with many Set commands in Windows PowerShell to return information about the result in cases in which there is no default output. 
You can specify paths relative to your current location in the same way as you would in most UNIX and Windows command shells. In standard notation for relative paths, a period (.)represents your current folder, and a doubled period (..) represents the parent directory of your current location. 
For example, if you are in the C:\Windows folder, a period (.)represents C:\Windows and double periods (..) represent C:. You can change from your current location to the root of the C: drive by typing:
PS> Set-Location -Path .. -PassThru
Path
----
C:\
The same technique works on Windows PowerShell drives that are not file system drives, such as HKLM:. You can set your location to the HKLM\Software key in the registry by typing:
 PS> Set-Location -Path HKLM:\SOFTWARE -PassThru

Path
----
HKLM:\SOFTWARE
You can then change the directory location to the parent directory, which is the root of the Windows PowerShell HKLM: drive, by using a relative path:
PS> Set-Location -Path .. -PassThru

Path
----
HKLM:\

You can type Set-Location or use any of the built-in Windows PowerShell aliases for Set-Location (cd, chdir, sl). For example:
cd -Path C:\Windows
chdir -Path .. -PassThru
sl -Path HKLM:\SOFTWARE -PassThru

Saving and Recalling Recent Locations (Push-Location and Pop-Location)
When changing locations, it is helpful to keep track of where you have been and to be able to return to your previous location. The Push-Location cmdlet in Windows PowerShell creates a ordered history (a "stack") of directory paths where you have been, and you can step back through the history of directory paths by using the complementary Pop-Location cmdlet. 
For example, a Windows PowerShell session typically starts in the user's home directory.
 PS> Get-Location

Path
----
C:\Documents and Settings\PowerUser 
Note
·	The word stack has a special meaning in many programming settings, including .NET. Like a physical stack of items, the last item you put onto the stack is the first item that you can pull off the stack. Adding an item to a stack is colloquially known as "pushing" the item onto the stack. Pulling an item off the stack is colloquially known as "popping" the item off the stack.
To push the current location onto the stack, and then move to the Local Settings folder, type:
 PS> Push-Location -Path "Local Settings"
You can then push the Local Settings location onto the stack and and move to the Temp folder by typing:
PS> Push-Location -Path Temp
You can verify that you changed directories by entering the Get-Location command:
PS> Get-Location

Path
----
C:\Documents and Settings\PowerUser\Local Settings\Temp
You can then pop back into the most recently visited directory by entering the Pop-Location command, and verify the change by entering the Get-Location command:
PS> Pop-Location
PS> Get-Location

Path
----
C:\Documents and Settings\me\Local Settings
Just as with the Set-Location cmdlet, you can include the -PassThru parameter when you enter the Pop-Location cmdlet to display the directory that you entered:
PS> Pop-Location -PassThru

Path
----
C:\Documents and Settings\PowerUser
You can also use the Location cmdlets with network paths. If you have a server named FS01 with an share named Public, you can change your location by typing
Set-Location \\FS01\Public

or
Push-Location \\FS01\Public
You can use the Push-Location and Set-Location commands to change the location to any available drive. For example, if you have a local CD-ROM drive with drive letter D that contains a data CD, you can change the location to the CD drive by entering the Set-Location D: command. 
If the drive is empty, you will get the following error message:
PS> Set-Location D:
Set-Location : Cannot find path 'D:\' because it does not exist.
When you are using a command-line interface, it is not convenient to use Windows Explorer to examine the available physical drives. Also, Windows Explorer would not show you the all of the Windows PowerShell drives. Windows PowerShell provides a set of commands for manipulating Windows PowerShell drives. and we will talk about these next.
Managing Windows PowerShell Drives
A Windows PowerShell drive is a data store location that you can access like a file system drive in Windows Powershell. The Windows PowerShell providers create some drives for you, such as the file system drives (including C: and D:), the registry drives (HKCU: and HKLM:), and the certificate drive (Cert:), and you can create your own Windows PowerShell drives. These drives are very useful, but they are available only within Windows PowerShell. You cannot access them by using other Windows tools, such as Windows Explorer or Cmd.exe.
Windows PowerShell uses the noun, PSDrive, for commands that work with Windows PowerShell drives. For a list of the Windows PowerShell drives in your session, use the Get-PSDrive cmdlet.
PS> Get-PSDrive

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
A          FileSystem    A:\
Alias      Alias
C          FileSystem    C:\                                 ...And Settings\me
cert       Certificate   \
D          FileSystem    D:\
Env        Environment
Function   Function
HKCU       Registry      HKEY_CURRENT_USER
HKLM       Registry      HKEY_LOCAL_MACHINE
Variable   Variable
Although the drives in the display vary with the drives on your system, the listing will look similar to the output of the Get-PSDrive command shown above.
File system drives are a subset of the Windows PowerShell drives. You can identify the file system drives by the FileSystem entry in the Provider column. (The file system drives in Windows PowerShell are supported by the Windows PowerShell FileSystem provider.)
To see the syntax of the Get-PSDrive cmdlet, type a Get-Command command with the Syntax parameter:
PS> Get-Command -Name Get-PSDrive -Syntax
Get-PSDrive [[-Name] <String[]>] [-Scope <String>] [-PSProvider <String[]>] [-V
erbose] [-Debug] [-ErrorAction <ActionPreference>] [-ErrorVariable <String>] [-
OutVariable <String>] [-OutBuffer <Int32>] 
The PSProvider parameter lets you display only the Windows PowerShell drives that are supported by a particular provider. For example, to display only the Windows PowerShell drives that are supported by the Windows PowerShell FileSystem provider, type a Get-PSDrive command with the PSProvider parameter and the FileSystem value:
PS> Get-PSDrive -PSProvider FileSystem

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
A          FileSystem    A:\
C          FileSystem    C:\                           ...nd Settings\PowerUser
D          FileSystem    D:\
To view the Windows PowerShell drives that represent registry hives, use the PSProvider parameter to display only the Windows PowerShell drives that are supported by the Windows PowerShell Registry provider:
PS> Get-PSDrive -PSProvider Registry

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
HKCU       Registry      HKEY_CURRENT_USER
HKLM       Registry      HKEY_LOCAL_MACHINE
You can also use the standard Location cmdlets with the Windows PowerShell drives:
PS> Set-Location HKLM:\SOFTWARE
PS> Push-Location .\Microsoft
PS> Get-Location

Path
----
HKLM:\SOFTWARE\Microsoft
Adding New Windows PowerShell Drives (New-PSDrive)
You can add your own Windows PowerShell drives by using the New-PSDrive command. To get the syntax for the New-PSDrive command, enter the Get-Command command with the Syntax parameter:
PS> Get-Command -Name New-PSDrive -Syntax
New-PSDrive [-Name] <String> [-PSProvider] <String> [-Root] <String> [-Descript
ion <String>] [-Scope <String>] [-Credential <PSCredential>] [-Verbose] [-Debug
] [-ErrorAction <ActionPreference>] [-ErrorVariable <String>] [-OutVariable <St
ring>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm]
To create a new Windows PowerShell drive, you must supply three parameters:
·	A name for the drive (you can use any valid Windows PowerShell name)
·	The PSProvider (use "FileSystem" for file system locations and "Registry" for registry locations)
·	The root, that is, the path to the root of the new drive
For example, you can create a drive named "Office" that is mapped to the folder that contains the Microsoft Office applications on your computer, such as C:\Program Files\Microsoft Office\OFFICE11. To create the drive, type the following command:
PS> New-PSDrive -Name Office -PSProvider FileSystem -Root "C:\Program Files\Micr
osoft Office\OFFICE11"

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
Office     FileSystem    C:\Program Files\Microsoft Offic...
Note
·	 In general, paths are not case-sensitive.
You refer to the new Windows PowerShell drive as you do all Windows PowerShell drives -- by its name followed by a colon (:).
A Windows PowerShell drive can make many tasks much simpler. For example, some of the most important keys in the Windows registry have extremely long paths, making them cumbersome to access and difficult to remember. Critical configuration information resides under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion. To view and change items in the CurrentVersion registry key, you can create a Windows PowerShell drive that is rooted in that key by typing:
PS> New-PSDrive -Name cvkey -PSProvider Registry -Root HKLM\Software\Microsoft\W
indows\CurrentVersion

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
cvkey      Registry      HKLM\Software\Microsoft\Windows\...
You can then change location to the cvkey: drive as you would any other drive:
PS> cd cvkey:
or:
PS> Set-Location cvkey: -PassThru

Path
----
cvkey:\
The New-PsDrive cmdlet adds the new drive only to the current console session. If you exit the console or close the Windows PowerShell window, the new drive is lost. To save a Windows PowerShell drive, use the Export-Console cmdlet to export the current console, and then use the PowerShell.exe PSConsoleFile parameter to import it into a new session. Or, add the new drive to your Windows PowerShell profile.
Deleting Windows PowerShell Drives (Remove-PSDrive)
You can delete drives from Windows PowerShell by using the Remove-PSDrive cmdlet. The Remove-PSDrive cmdlet is easy to use; to delete a specific Windows PowerShell drive, you just supply the Windows PowerShell drive name. 
For example, if you added the Office: Windows PowerShell drive, as shown in the New-PSDrive topic, you can delete it by typing:
PS> Remove-PSDrive -Name Office
To delete the cvkey: Windows PowerShell drive, also shown in the New-PSDrive topic, use the following command:
PS> Remove-PSDrive -Name cvkey
It's easy to delete a Windows PowerShell drive, but you can't delete it while you are in the drive. For example:
PS> cd office:
PS Office:\> remove-psdrive -name office
Remove-PSDrive : Cannot remove drive 'Office' because it is in use.
At line:1 char:15
+ remove-psdrive  <<<< -name office
Adding and Removing Drives Outside Windows PowerShell
Windows PowerShell detects file system drives that are added or removed in Windows, including network drives that are mapped, USB drives that are attached, and drives that are deleted by using either the net use command or the WScript.NetworkMapNetworkDrive and RemoveNetworkDrive methods from a Windows Script Host (WSH) script.
Working With Files, Folders and Registry Keys
Windows PowerShell uses the noun Item to refer to things found on a Windows PowerShell drive. When dealing with the Windows PowerShell FileSystem provider, an Item might be a file, a folder, or the Windows PowerShell drive. Listing and working with these items is a critical basic task in most administrative settings, so we want to discuss these tasks in detail.
Enumerating Files, Folders, and Registry Keys (Get-ChildItem)
Since getting a collection of items from a particular location is such a common task, the Get-ChildItem cmdlet is designed specifically to returning all items found within a container such as a folder. 
If you want to return all files and folders that are contained directly within the folder C:\Windows, type:
PS> Get-ChildItem -Path C:\Windows
    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\Windows
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2006-05-16   8:10 AM          0 0.log
-a---        2005-11-29   3:16 PM         97 acc1.txt
-a---        2005-10-23  11:21 PM       3848 actsetup.log
...
The listing looks similar to what you would see when you enter the dir command in Cmd.exe, or the ls command in a UNIX command shell.
You can perform very complex listings by using parameters of the Get-ChildItem cmdlet. We will look at a few scenarios next. You can see the syntax the Get-ChildItem cmdlet by typing:
PS> Get-Command -Name Get-ChildItem -Syntax
These parameters can be mixed and matched to get highly customized output.
Listing all Contained Items (-Recurse)
To see both the items inside a Windows folder and any items that are contained within the subfolders, use the Recurse parameter of Get-ChildItem. The listing displays everything within the Windows folder and the items in its subfolders. For example:
PS> Get-ChildItem -Path C:\WINDOWS -Recurse

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\WINDOWS
    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\WINDOWS\AppPatch
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2004-08-04   8:00 AM    1852416 AcGenral.dll
...
Filtering Items by Name (-Name)
To display only the names of items, use the Name parameter of Get-Childitem:
PS> Get-ChildItem -Path C:\WINDOWS -Name
addins
AppPatch
assembly
...
Forcibly Listing Hidden Items (-Force)
Items that are normally invisible in Windows Explorer or Cmd.exe are not displayed in the output of a Get-ChildItem command. To display hidden items, use the Force parameter of Get-ChildItem. For example:
Get-ChildItem -Path C:\Windows -Force
This parameter is named Force because you can forcibly override the normal behavior of the Get-ChildItem command. Force is a widely used parameter that forces an action that a cmdlet would not normally perform, although it will not perform any action that compromises the security of the system.
Matching Item Names with Wildcards
The Get-ChildItem command accepts wildcards in the path of the items to list. 
Because wildcard matching is handled by the Windows PowerShell engine, all cmdlets that accepts wildcards use the same notation and have the same matching behavior. The Windows PowerShell wildcard notation includes:
·	Asterisk (*)matches zero or more occurrences of any character.
·	Question mark (?) matches exactly one character.
·	Left bracket ([) character and right bracket (]) character surround a set of characters to be matched. 
Here are some examples of how wildcard specification works.
To find all files in the Windows directory with the suffix .log and exactly five characters in the base name, enter the following command:
PS> Get-ChildItem -Path C:\Windows\?????.log
    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\Windows
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
...
-a---        2006-05-11   6:31 PM     204276 ocgen.log
-a---        2006-05-11   6:31 PM      22365 ocmsn.log
...
-a---        2005-11-11   4:55 AM         64 setup.log
-a---        2005-12-15   2:24 PM      17719 VxSDM.log
...
To find all files that begin with the letter x in the Windows directory, type:
 Get-ChildItem -Path C:\Windows\x*
To find all files whose names begin with x or z, type:
Get-ChildItem -Path C:\Windows\[xz]*
Excluding Items (-Exclude)
You can exclude specific items by using the Exclude parameter of Get-ChildItem. This lets you perform complex filtering in a single statement.
For example, suppose you are trying to find the Windows Time Service DLL in the System32 folder, and all you can remember about the DLL name is that it begins with "W" and has "32" in it.  
An expression like w*32*.dll will find all DLLs that satisfy the conditions, but it may also return the Windows 95 and 16-bit Windows compatibility DLLs that include "95" or "16" in their names. You can omit files that have any of these numbers in their names by using the Exclude parameter with the pattern *[9516]*:  
 PS> Get-ChildItem -Path C:\WINDOWS\System32\w*32*.dll -Exclude *[9516]*

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS\System32

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2004-08-04   8:00 AM     174592 w32time.dll
-a---        2004-08-04   8:00 AM      22016 w32topl.dll
-a---        2004-08-04   8:00 AM     101888 win32spl.dll
-a---        2004-08-04   8:00 AM     172032 wldap32.dll
-a---        2004-08-04   8:00 AM     264192 wow32.dll
-a---        2004-08-04   8:00 AM      82944 ws2_32.dll
-a---        2004-08-04   8:00 AM      42496 wsnmp32.dll
-a---        2004-08-04   8:00 AM      22528 wsock32.dll
-a---        2004-08-04   8:00 AM      18432 wtsapi32.dll
Mixing Get-ChildItem Parameters
You can use several of the parameters of the Get-ChildItem cmdlet in the same command. Before you mix parameters, be sure that you understand wildcard matching. For example, the following command returns no results:
PS> Get-ChildItem -Path C:\Windows\*.dll -Recurse -Exclude [a-y]*.dll
There are no results, even though there are two DLLs that begin with the letter "z" in the Windows folder. 
No results were returned because we specified the wildcard as part of the path. Even though the command was recursive, the Get-ChildItem cmdlet restricted the items to those that are in the Windows folder with names end with ".dll".
To specify a recursive search for files whose names match a special pattern, use the -Include parameter. 
PS> Get-ChildItem -Path C:\Windows -Include *.dll -Recurse -Exclude [a-y]*.dll

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\Windows\System32\Setup

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2004-08-04   8:00 AM       8261 zoneoc.dll

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\Windows\System32

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2004-08-04   8:00 AM     337920 zipfldr.dll

Manipulating Items Directly
The elements that you see in Windows PowerShell drives, such as the files and folders in the file system drives, and the registry keys in the Windows PowerShell registry drives, are called items in Windows PowerShell. The cmdlets for working with them item have the noun Item in their names. 
The output of the Get-Command -Noun Item command shows that there are nine Windows PowerShell item cmdlets.
PS> Get-Command -Noun Item

CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Clear-Item                      Clear-Item [-Path] <String[]...
Cmdlet          Copy-Item                       Copy-Item [-Path] <String[]>...
Cmdlet          Get-Item                        Get-Item [-Path] <String[]> ...
Cmdlet          Invoke-Item                     Invoke-Item [-Path] <String[...
Cmdlet          Move-Item                       Move-Item [-Path] <String[]>...
Cmdlet          New-Item                        New-Item [-Path] <String[]> ...
Cmdlet          Remove-Item                     Remove-Item [-Path] <String[...
Cmdlet          Rename-Item                     Rename-Item [-Path] <String>...
Cmdlet          Set-Item                        Set-Item [-Path] <String[]> ...
Creating New Items (New-Item)
To create a new item in the file system, use the New-Item cmdlet. Include the Path parameter with path to the item, and the ItemType parameter with a value of "file" or "directory". 
For example, to create a new directory named "New.Directory"in the C:\Temp directory,  type:
PS> New-Item -Path c:\temp\New.Directory -ItemType Directory

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\temp

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2006-05-18  11:29 AM            New.Directory
To create a file, change the value of the ItemType parameter to "file". For example, to create a file named "file1.txt" in the New.Directory directory, type:
PS> New-Item -Path C:\temp\New.Directory\file1.txt -ItemType file

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\temp\New.Directory

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2006-05-18  11:44 AM          0 file1
You can use the same technique to create a new registry key. In fact, a registry key is easier to create because the only item type in the Windows registry is a key. (Registry entries are item properties.) For example, to create a key named "_Test" in the CurrentVersion subkey, type:
PS> New-Item -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\_Test

   Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Micros
oft\Windows\CurrentVersion

SKC  VC Name                           Property
---  -- ----                           --------
  0   0 _Test                          {}
When typing a registry path, be sure to include the colon (:) in the Windows PowerShell drive names, HKLM: and HKCU:. Without the colon, Windows PowerShell does not recognize the drive name in the path.
Why Registry Values are not Items
When you use the Get-ChildItem cmdlet to find the items in a registry key, you will never see actual registry entries or their values. 
For example, the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run usually contains several registry entries that represent applications that run when the system starts. 
However, when you use Get-ChildItem to look for child items in the key, all you will see is the OptionalComponents subkey of the key:
PS> Get-ChildItem HKLM:\Software\Microsoft\Windows\CurrentVersion\Run
   Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Micros
oft\Windows\CurrentVersion\Run
SKC  VC Name                           Property
---  -- ----                           --------
  3   0 OptionalComponents             {}
Although it would be convenient to treat registry entries as items, you cannot specify a path to a registry entry in a way that ensures that it is unique. The path notation does not distinguish between the registry subkey named Run and the (Default) registry entry in the Run subkey. Furthermore, because registry entry names can contain the backslash character (\), if regsitry entries were items, then you could not use the path notation to distinguish a registry entry named Windows\CurrentVersion\Run from the subkey that is located in that path.
Renaming Existing Items (Rename-Item)
To change the name of a file or folder, use the Rename-Item cmdlet. The following command changes the name of the file1.txt file to fileOne.txt.
PS> Rename-Item -Path C:\temp\New.Directory\file1.txt fileOne.txt
The Rename-Item cmdlet can change the name of a file or a folder, but it cannot move an item. The following command fails because it attempts to move the file from the New.Directory directory to the Temp directory.
PS> Rename-Item -Path C:\temp\New.Directory\fileOne.txt c:\temp\fileOne.txt
Rename-Item : Cannot rename because the target specified is not a path.
At line:1 char:12
+ Rename-Item  <<<< -Path C:\temp\New.Directory\fileOne c:\temp\fileOne.txt
Moving Items (Move-Item)
To move a file or folder, use the Move-Item cmdlet. 
For example, the following command moves the New.Directory directory from the C:\temp directory to the root of the C: drive. To verify that the item was moved, include the PassThru parameter of the Move-Item cmdlet. Without Passthru, the Move-Item cmdlet does not display any results.
PS> Move-Item -Path C:\temp\New.Directory -Destination C:\ -PassThru

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2006-05-18  12:14 PM            New.Directory
Copying Items (Copy-Item)
If you are familiar with the copy operations in other shells, you might find the behavior of the Copy-Item cmdlet in Windows PowerShell to be unusual. When you copy an item from one location to another, Copy-Item does not copy its contents by default.
For example, if you copy the New.Directory directory from the C: drive to the C:\temp directory, the command succeeds, but the files in the New.Directory directory are not copied.
PS> Copy-Item -Path C:\New.Directory -Destination C:\temp
If you display the contents of C:\temp\New.Directory, you will find that it contains no files:
PS> Get-ChildItem -Path C:\temp\New.Directory
PS>
Why doesn't the Copy-Item cmdlet copy the contents to the new location?
The Copy-Item cmdlet was designed to be generic; it is not just for copying files and folders. Also, even when copying files and folders, you might want to copy only the container and not the items within it. 
To copy all of the contents of a folder, include the Recurse parameter of the Copy-Item cmdlet in the command. If you have already copied the directory without its contents, add the Force parameter, which allows you to overwrite the empty folder.
PS> Copy-Item -Path C:\New.Directory -Destination C:\temp -Recurse -Force -Passthru
    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\temp

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2006-05-18   1:53 PM            New.Directory

    Directory: Microsoft.Windows PowerShell.Core\FileSystem::C:\temp\New.Directory

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2006-05-18  11:44 AM          0 file1
Deleting Items (Remove-Item)
To delete files and folders, use the Remove-Item cmdlet. Windows PowerShell cmdlets, such as Remove-Item, that can make significant, irreversible changes will often prompt for confirmation when you enter its commands. For example, if you try to remove the New.Directory folder, you will be prompted to confirm the command, because the folder contains files:
PS> Remove-Item C:\New.Directory

Confirm
The item at C:\temp\New.Directory has children and the -recurse parameter was not
specified. If you continue, all children will be removed with the item. Are you
 sure you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):
Because Yes is the default response, to delete the folder and its files, press the Enter key. To remove the folder without confirming, use the -Recurse parameter.
PS> Remove-Item C:\temp\New.Directory -Recurse
Executing Items (Invoke-Item)
Windows PowerShell uses the Invoke-Item cmdlet to perform a default action for a file or folder. This default action is determined by the default application handler in the registry; the effect is the same as if you double-click the item in Windows Explorer.
For example, suppose you run the following command: 
PS> Invoke-Item C:\WINDOWS
An Explorer window that is located in C:\Windows appears, just as if you had double-clicked the C:\Windows folder.
If you invoke the Boot.ini file on a system prior to Windows Vista:
PS> Invoke-Item C:\boot.ini
If the .ini file type is associated with Notepad, the boot.ini file opens in Notepad.
Working with Objects
 We have discussed how Windows PowerShell uses objects to transfer data between cmdlets, and demonstrated a few ways to view detailed information about objects by using Get-Member and Format cmdlets to view particular properties of objects.
The power of objects is that they provide you with access to a lot of complex data and it is already correlated. With some simple techniques you can further manipulate objects to do even more work. We are going to look at some specific types of objects and ways you can manipulate them in this chapter.
Getting WMI Objects (Get-WmiObject)
Getting WMI Objects (Get-WmiObject)
Windows Management Instrumentation (WMI) is a core technology for Windows system administration because it exposes a wide range of information in a uniform manner. Because of how much WMI makes possible, the Windows PowerShell cmdlet for accessing WMI objects, Get-WmiObject, is one of the most useful for doing real work. We are going to discuss how to use Get-WmiObject to access WMI objects and then how to use WMI objects to do specific things. 
Listing WMI Classes
The first problem most WMI users encounter is trying to find out what can be done with WMI. WMI classes describe the resources that can be managed. There are hundreds of WMI classes, some of which contain dozens of properties. 
Get-WmiObject addresses this problem by making WMI discoverable. You can get a list of the WMI classes available on the local computer by typing: 
PS> Get-WmiObject -List

__SecurityRelatedClass                  __NTLMUser9X
__PARAMETERS                            __SystemSecurity
__NotifyStatus                          __ExtendedStatus
Win32_PrivilegesStatus                  Win32_TSNetworkAdapterSettingError
Win32_TSRemoteControlSettingError       Win32_TSEnvironmentSettingError
...
You can retrieve the same information from a remote computer by using the ComputerName parameter, specifying a computer name or IP address:
PS> Get-WmiObject -List -ComputerName 192.168.1.29

__SystemClass                           __NAMESPACE
__Provider                              __Win32Provider
__ProviderRegistration                  __ObjectProviderRegistration
...
The class listing returned by remote computers may vary due to the specific operating system the computer is running and the particular WMI extensions added by installed applications.
Note: 
When using Get-WmiObject to connect to a remote computer, the remote computer must be running WMI and, under the default configuration, the account you are using must be in the local administrators group on the remote computer. The remote system does not need to have Windows PowerShell installed. This allows you to administer operating systems that are not running Windows PowerShell, but do have WMI available.
You can even include the ComputerName when connecting to the local system. You can use the local computer's name, its IP address (or the loopback address 127.0.0.1), or the WMI-style '.' as the computer name. If you are running Windows PowerShell on a computer named Admin01 with IP address 192.168.1.90, the following commands will all return the WMI class listing for that computer:
Get-WmiObject -List
Get-WmiObject -List -ComputerName .
Get-WmiObject -List -ComputerName Admin01
Get-WmiObject -List -ComputerName 192.168.1.90
Get-WmiObject -List -ComputerName 127.0.0.1
Get-WmiObject -List -ComputerName localhost
Get-WmiObject uses the root/cimv2 namespace by default. If you want to specify another WMI namespace, use the Namespace parameter and specify the corresponding namespace path:
PS> Get-WmiObject -List -ComputerName 192.168.1.29 -Namespace root

__SystemClass                           __NAMESPACE
__Provider                              __Win32Provider
...
Displaying WMI Class Details
If you already know the name of a WMI class, you can use it to get information immediately. For example, one of the WMI classes commonly used for retrieving information about a computer is Win32_OperatingSystem. 
PS> Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ComputerName .

SystemDirectory : C:\WINDOWS\system32
Organization    : Global Network Solutions
BuildNumber     : 2600
RegisteredUser  : Oliver W. Jones
SerialNumber    : 12345-678-9012345-67890
Version         : 5.1.2600
Although we are showing all of the parameters, the command can be expressed in a more succinct way. The ComputerName parameter is not necessary when connecting to the local system. We show it to demonstrate the most general case and remind you about the parameter. The Namespace defaults to root/cimv2, and can be omitted as well. Finally, most cmdlets allow you to omit the name of common parameters. With Get-WmiObject, if no name is specified for the first parameter, Windows PowerShell treats it as the Class parameter. This means the last command could have been issued by typing:
Get-WmiObject Win32_OperatingSystem
The Win32_OperatingSystem class has many more properties than those displayed here. You can use Get-Member to see all the properties. The properties of a WMI class are automatically available like other object properties:
PS> Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ComputerName . | Get-Member -MemberType Property

   TypeName: System.Management.ManagementObject#root\cimv2\Win32_OperatingSyste
m

Name                                      MemberType Definition
----                                      ---------- ----------
__CLASS                                   Property   System.String __CLASS {...
...
BootDevice                                Property   System.String BootDevic...
BuildNumber                               Property   System.String BuildNumb...
...
Displaying Non-Default Properties with Format Cmdlets
If you want information contained in the Win32_OperatingSystem class that is not displayed by default, you can display it by using the Format cmdlets. For example, if you wish to display available memory data, type:
PS> Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ComputerName . | Format-Table -Property TotalVirtualMemorySize,TotalVisibleMemorySize,FreePhysicalMemory,FreeVirtualMemory,FreeSpaceInPagingFiles

TotalVirtualMemorySize TotalVisibleMem FreePhysicalMem FreeVirtualMemo FreeSpaceInPagi
                              ory              ry         ngFiles
--------------- --------------- --------------- --------------- ---------------
        2097024          785904          305808         2056724         1558232
Note
·	Wildcards work with property names in Format-Table, so the final pipeline element can be reduced to Format-Table -Property TotalV*,Free*
The memory data might be more readable if you format it as a list by typing:
PS> Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ComputerName . | Format-List TotalVirtualMemorySize,TotalVisibleMemorySize,FreePhysicalMemory,FreeVirtualMemory,FreeSpaceInPagingFiles

TotalVirtualMemorySize : 2097024
TotalVisibleMemorySize : 785904
FreePhysicalMemory     : 301876
FreeVirtualMemory      : 2056724
FreeSpaceInPagingFiles : 1556644
Creating .NET and COM Objects (New-Object)
There are software components with .NET Framework and COM interfaces that enable you to perform many system administration tasks. Windows PowerShell lets you use these components, so you are not limited to the tasks that can be performed by using cmdlets. Many of the cmdlets in the initial release of Windows PowerShell do not work against remote computers. We will demonstrate how to get around this limitation when managing event logs by using the .NET System.Diagnostics.EventLog class directly from Windows PowerShell.
Using New-Object for Event Log Access
The .NET Framework Class Library includes a class named System.Diagnostics.EventLog that can be used to manage event logs. You can create a new instance of a .NET class by using the New-Object cmdlet with the TypeName parameter. For example, the following command creates an event log reference:
PS> New-Object -TypeName System.Diagnostics.EventLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
Although the command has created an instance of the EventLog class, the instance does not include any data. That is because we did not specify a particular event log. How do you get a real event log?
Using Constructors with New-Object
To refer to a specific event log, you need to specify the name of the log. New-Object has an ArgumentList parameter. The arguments you pass as values to this parameter are used by a special startup method of the object. The method is called a constructor because it is used to construct the object. For example, to get a reference to the Application log, you specify the string 'Application' as an argument:
PS> New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application

Max(K) Retain OverflowAction        Entries Name
------ ------ --------------        ------- ----
16,384      7 OverwriteOlder          2,160 Application
Note: 
Since most of the .NET core classes are contained in the System namespace, Windows PowerShell will automatically attempt to find classes you specify in the System namespace if it cannot find a match for the typename you specify. This means that you can specify Diagnostics.EventLog instead of System.Diagnostics.EventLog.
Storing Objects in Variables
You might want to store a reference to an object, so you can use it during a Windows PowerShell session. Although Windows PowerShell lets you do a lot of work with pipelines, lessening the need for variables, sometimes storing references to objects in variables makes it more convenient to manipulate those objects.
Windows PowerShell lets you create variables that are essentially named objects. The output from any valid Windows PowerShell command can be stored in a variable. Variable names always begin with $. If you want to store the Application log reference in a variable named $AppLog, type the name of the variable, followed by an equal sign and then type the command used to create the Application log object:
PS> $AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
If you then type $AppLog, you can see that it contains the Application log:
PS> $AppLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
  16,384      7 OverwriteOlder          2,160 Application
Accessing a Remote Event Log with New-Object
The commands used in the preceding section target the local computer; the Get-EventLog cmdlet can do that. To access the Application log on a remote computer, you must supply both the log name and a computer name (or IP address) as arguments.
PS> $RemoteAppLog = New-Object -TypeName System.Diagnostics.EventLog Application,192.168.1.81
PS> $RemoteAppLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
     512      7 OverwriteOlder            262 Application
Now that we have a reference to an event log stored in the $RemoteAppLog variable, what tasks can we perform on it?
Clearing an Event Log with Object Methods
Objects often have methods that can be called to perform tasks. You can use Get-Member to display the methods associated with an object. The following command and selected output show some the methods of the EventLog class:
PS> $RemoteAppLog | Get-Member -MemberType Method

   TypeName: System.Diagnostics.EventLog

Name                      MemberType Definition
----                      ---------- ----------
...
Clear                     Method     System.Void Clear()
Close                     Method     System.Void Close()
...
GetType                   Method     System.Type GetType()
...
ModifyOverflowPolicy      Method     System.Void ModifyOverflowPolicy(Overfl...
RegisterDisplayName       Method     System.Void RegisterDisplayName(String ...
...
ToString                  Method     System.String ToString()
WriteEntry                Method     System.Void WriteEntry(String message),...
WriteEvent                Method     System.Void WriteEvent(EventInstance in...
The Clear() method can be used to clear the event log. When calling a method, you must always follow the method name by parentheses, even if the method does not require arguments. This lets Windows PowerShell distinguish between the method and a potential property with the same name. Type the following to call the Clear method:
PS> $RemoteAppLog.Clear()
Type the following to display the log. You will see that the event log was cleared, and now has 0 entries instead of 262:
PS> $RemoteAppLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
     512      7 OverwriteOlder              0 Application
Creating COM Objects with New-Object
You can use New-Object to work with Component Object Model (COM) components. Components range from the various libraries included with Windows Script Host (WSH) to ActiveX applications such as Internet Explorer that are installed on most systems.
New-Object uses .NET Framework Runtime-Callable Wrappers to create COM objects, so it has the same limitations that .NET does when calling COM objects. To create a COM object, you need to specify the ComObject parameter with the Programmatic Identifier or ProgId of the COM class you want to use. A complete discussion of the limitations of COM use and determining what ProgIds are available on a system is beyond the scope of this Primer, but most well-known objects from environments such as WSH can be used within Windows PowerShell.
You can create the WSH objects by specifying these progids: WScript.Shell, WScript.Network, Scripting.Dictionary, and Scripting.FileSystemObject. The following commands create these objects:
New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject
Although most of the functionality of these classes is made available in other ways in Windows PowerShell, a few tasks such as shortcut creation are still easier to do using the WSH classes.
Creating a Desktop Shortcut with WScript.Shell
One task that can be performed quickly with a COM object is creating a shortcut. Suppose you want to create a shortcut on your desktop that links to the home folder for Windows PowerShell. You first need to create a reference to WScript.Shell, which we will store in a variable named $WshShell:
$WshShell = New-Object -ComObject WScript.Shell
Get-Member works with COM objects, so you can explore the members of the object by typing:
PS> $WshShell | Get-Member

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

Name                     MemberType            Definition
----                     ----------            ----------
AppActivate              Method                bool AppActivate (Variant, Va...
CreateShortcut           Method                IDispatch CreateShortcut (str...
...
Note
·	Get-Member has an optional InputObject parameter you can use instead of piping to provide input to Get-Member. You would get the same output as shown above if you instead used the command Get-Member -InputObject $WshShell. If you use InputObject, it treats its argument as a single item. This means that if you have several objects in a variable, Get-Member treats them as an array of objects. For example:
·	PS> $a = 1,2,"three"
·	PS> Get-Member -InputObject $a
·	   TypeName: System.Object[]
·	Name               MemberType    Definition
·	----               ----------    ----------
·	Count              AliasProperty Count = Length
·	...
The WScript.Shell CreateShortcut method accepts a single argument, the path to the shortcut file to create. We could type in the full path to the desktop, but there is an easier way. The desktop is normally represented by a folder named Desktop inside the home folder of the current user. Windows PowerShell has a variable $Home that contains the path to this folder. We can specify the path to the home folder by using this variable, and then add the name of the Desktop folder and the name for the shortcut to create by typing:
$lnk = $WshShell.CreateShortcut("$Home\Desktop\PSHome.lnk")
Note
·	When you use something that looks like a variable name inside double-quotes, Windows PowerShell tries to substitute a matching value. If you use single-quotes, Windows PowerShell does not try to substitute the variable value. For example, try typing the following commands:
·	PS> "$Home\Desktop\PSHome.lnk"
·	C:\Documents and Settings\aka\Desktop\PSHome.lnk
·	PS> '$Home\Desktop\PSHome.lnk'
·	$Home\Desktop\PSHome.lnk

We now have a variable named $lnk that contains a new shortcut reference. If you want to see its members, you can pipe it to Get-Member. The output below shows the members we need to use to finish creating our shortcut: 
PS> $lnk | Get-Member

   TypeName: System.__ComObject#{f935dc23-1cf0-11d0-adb9-00c04fd58a0b}

Name             MemberType   Definition
----             ----------   ----------
...
Save             Method       void Save ()
...
TargetPath       Property     string TargetPath () {get} {set}
...
We need to specify the TargetPath, which is the application folder for Windows PowerShell, and then save the shortcut $lnk by calling the Save method. The Windows PowerShell application folder path is stored in the variable $PSHome, so we can do this by typing:
$lnk.TargetPath = $PSHome
$lnk.Save()
Using Internet Explorer from Windows PowerShell
Many applications (including the Microsoft Office family of applications and Internet Explorer) can be automated by using COM. Internet Explorer illustrates some of the typical techniques and issues involved in working with COM-based applications.
You create an Internet Explorer instance by specifying the Internet Explorer ProgId, InternetExplorer.Application:
$ie = New-Object -ComObject InternetExplorer.Application
This command starts Internet Explorer, but does not make it visible. If you type Get-Process, you can see that a process named iexplore is running. In fact, if you exit Windows PowerShell, the process will continue to run. You must reboot the computer or use a tool like Task Manager to end the iexplore process.
Note: 
COM objects that start as separate processes, commonly called ActiveX executables, may or may not display a user interface window when they start up.  If they create a window but do not make it visible, like Internet Explorer, the focus will generally move to the Windows desktop and you must make the window visible to interact with it. 
By typing $ie | Get-Member, you can view properties and methods for Internet Explorer. To see the Internet Explorer window, set the Visible property to $true by typing:
$ie.Visible = $true
You can then navigate to a specific web address by using the Navigate method:
$ie.Navigate("http://www.microsoft.com/technet/scriptcenter/default.mspx")
Using other members of the Internet Explorer object model, it is possible to retrieve text content from the web page. The following command will display the HTML text in the body of the current web page:
$ie.Document.Body.InnerText
To close Internet Explorer from within PowerShell, call its Quit() method:
$ie.Quit()
This will force it to close. The $ie variable no longer contains a valid reference even though it still appears to be a COM object. If you attempt to use it, you will get an automation error:
PS> $ie | Get-Member
Get-Member : Exception retrieving the string representation for property "Appli
cation" : "The object invoked has disconnected from its clients. (Exception fro
m HRESULT: 0x80010108 (RPC_E_DISCONNECTED))"
At line:1 char:16
+ $ie | Get-Member <<<<
You can either remove the remaining reference with a command like $ie = $null, or completely remove the variable by typing:
Remove-Variable ie
Note: 
There is no common standard for whether ActiveX executables exit or continue to run when you remove a reference to one. Depending on circumstances such as whether the application is visible, whether an edited document is running in it, and even whether Windows PowerShell is still running, the application may or may not exit. For this reason, you should test termination behavior for each ActiveX executable you want to use in Windows PowerShell.
Getting Warnings about .NET-Wrapped COM Objects
In some cases, a COM object might have an associated .NET Runtime-Callable Wrapper or RCW, and this will be used by New-Object. Since the behavior of the RCW may be different from the behavior of the normal COM object, New-Object has a Strict parameter to warn you about RCW access. If you specify the Strict parameter and then create a COM object that uses an RCW, you get a warning message:
PS> $xl = New-Object -ComObject Excel.Application -Strict
New-Object : The object written to the pipeline is an instance of the type "Mic
rosoft.Office.Interop.Excel.ApplicationClass" from the component's primary inte
rop assembly. If this type exposes different members than the IDispatch members
, scripts written to work with this object might not work if the primary intero
p assembly is not installed.
At line:1 char:17
+ $xl = New-Object  <<<< -ComObject Excel.Application -Strict
Although the object is still created, you are warned that it is not a standard COM object.
Using Static Classes and Methods
Not all .NET Framework classes can be created by using New-Object. For example, if you try to create a System.Environment or a System.Math object with New-Object, you will get the following error messages:
PS> New-Object System.Environment
New-Object : Constructor not found. Cannot find an appropriate constructor for
type System.Environment.
At line:1 char:11
+ New-Object  <<<< System.Environment
PS> New-Object System.Math
New-Object : Constructor not found. Cannot find an appropriate constructor for
type System.Math.
At line:1 char:11
+ New-Object  <<<< System.Math
These errors occur because there is no way to create a new object from these classes. These classes are reference libraries of methods and properties that do not change state. You don't need to create them, you simply use them. Classes and methods such as these are called static classes because they are not created, destroyed, or changed. To make this clear we will provide examples that use static classes.
Getting Environment Data with System.Environment
Usually, the first step in working with an object in Windows PowerShell is to use Get-Member to find out what members it contains. With static classes, the process is a little different because the actual class is not an object. 
Referring to the Static System.Environment Class
You can refer to a static class by surrounding the class name with square brackets. For example, you can refer to System.Environment by typing the name within brackets. Doing so displays some generic type information:
PS> [System.Environment]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Environment                              System.Object
Note: 
As we mentioned previously, Windows PowerShell automatically prepends  'System.' to type names when you use New-Object. The same thing happens when using a bracketed type name, so you can specify [System.Environment] as [Environment].
The System.Environment class contains general information about the working environment for the current process, which is powershell.exe when working within Windows PowerShell.
If you try to view details of this class by typing [System.Environment] | Get-Member, the object type is reported as being System.RuntimeType , not System.Environment:
PS> [System.Environment] | Get-Member

   TypeName: System.RuntimeType
To view static members with Get-Member, specify the Static parameter:
PS> [System.Environment] | Get-Member -Static

   TypeName: System.Environment

Name                       MemberType Definition
----                       ---------- ----------
Equals                     Method     static System.Boolean Equals(Object ob...
Exit                       Method     static System.Void Exit(Int32 exitCode)
...
CommandLine                Property   static System.String CommandLine {get;}
CurrentDirectory           Property   static System.String CurrentDirectory ...
ExitCode                   Property   static System.Int32 ExitCode {get;set;}
HasShutdownStarted         Property   static System.Boolean HasShutdownStart...
MachineName                Property   static System.String MachineName {get;}
NewLine                    Property   static System.String NewLine {get;}
OSVersion                  Property   static System.OperatingSystem OSVersio...
ProcessorCount             Property   static System.Int32 ProcessorCount {get;}
StackTrace                 Property   static System.String StackTrace {get;}
SystemDirectory            Property   static System.String SystemDirectory {...
TickCount                  Property   static System.Int32 TickCount {get;}
UserDomainName             Property   static System.String UserDomainName {g...
UserInteractive            Property   static System.Boolean UserInteractive ...
UserName                   Property   static System.String UserName {get;}
Version                    Property   static System.Version Version {get;}
WorkingSet                 Property   static System.Int64 WorkingSet {get;}
TickCount                               ExitCode
We can now select properties to view from System.Environment.
Displaying Static Properties of System.Environment
The properties of System.Environment are also static, and must be specified in a different way than normal properties. We use :: to indicate to Windows PowerShell that we want to work with a static method or property. To see the command that was used to launch Windows PowerShell, we check the CommandLine property by typing:
PS> [System.Environment]::Commandline
"C:\Program Files\Windows PowerShell\v1.0\powershell.exe"
To check the operating system version, display the OSVersion property by typing:
PS> [System.Environment]::OSVersion

           Platform ServicePack         Version             VersionString
           -------- -----------         -------             -------------
            Win32NT Service Pack 2      5.1.2600.131072     Microsoft Window...
We can check whether the computer is in the process of shutting down by displaying the HasShutdownStarted property:
PS> [System.Environment]::HasShutdownStarted
False  
Doing Math with System.Math
The System.Math static class is useful for performing some mathematical operations. The important members of System.Math are mostly methods, which we can display by using Get-Member. 
Note: 
System.Math has several methods with the same name, but they are distinguished by the type of their parameters.
Type the following command to list the methods of the System.Math class.
PS> [System.Math] | Get-Member -Static -MemberType Methods

   TypeName: System.Math

Name            MemberType Definition
----            ---------- ----------
Abs             Method     static System.Single Abs(Single value), static Sy...
Acos            Method     static System.Double Acos(Double d)
Asin            Method     static System.Double Asin(Double d)
Atan            Method     static System.Double Atan(Double d)
Atan2           Method     static System.Double Atan2(Double y, Double x)
BigMul          Method     static System.Int64 BigMul(Int32 a, Int32 b)
Ceiling         Method     static System.Double Ceiling(Double a), static Sy...
Cos             Method     static System.Double Cos(Double d)
Cosh            Method     static System.Double Cosh(Double value)
DivRem          Method     static System.Int32 DivRem(Int32 a, Int32 b, Int3...
Equals          Method     static System.Boolean Equals(Object objA, Object ...
Exp             Method     static System.Double Exp(Double d)
Floor           Method     static System.Double Floor(Double d), static Syst...
IEEERemainder   Method     static System.Double IEEERemainder(Double x, Doub...
Log             Method     static System.Double Log(Double d), static System...
Log10           Method     static System.Double Log10(Double d)
Max             Method     static System.SByte Max(SByte val1, SByte val2), ...
Min             Method     static System.SByte Min(SByte val1, SByte val2), ...
Pow             Method     static System.Double Pow(Double x, Double y)
ReferenceEquals Method     static System.Boolean ReferenceEquals(Object objA...
Round           Method     static System.Double Round(Double a), static Syst...
Sign            Method     static System.Int32 Sign(SByte value), static Sys...
Sin             Method     static System.Double Sin(Double a)
Sinh            Method     static System.Double Sinh(Double value)
Sqrt            Method     static System.Double Sqrt(Double d)
Tan             Method     static System.Double Tan(Double a)
Tanh            Method     static System.Double Tanh(Double value)
Truncate        Method     static System.Decimal Truncate(Decimal d), static...
This displays several mathematical methods. Here is a list of commands that demonstrate how some of the common methods work:
PS> [System.Math]::Sqrt(9)
3
PS> [System.Math]::Pow(2,3)
8
PS> [System.Math]::Floor(3.3)
3
PS> [System.Math]::Floor(-3.3)
-4
PS> [System.Math]::Ceiling(3.3)
4
PS> [System.Math]::Ceiling(-3.3)
-3
PS> [System.Math]::Max(2,7)
7
PS> [System.Math]::Min(2,7)
2
PS> [System.Math]::Truncate(9.3)
9
PS> [System.Math]::Truncate(-9.3)
-9
Removing Objects from the Pipeline (Where-Object)
In Windows PowerShell, you often generate and pass along more objects to a pipeline than you want. You can specify the properties of particular objects to display by using the Format cmdlets, but this does not help with the problem of removing entire objects from the display. You may want to filter objects before the end of a pipeline, so you can perform actions on only a subset of the initially-generated objects.
Windows PowerShell includes a Where-Object cmdlet that allows you to test each object in the pipeline and only pass it along the pipeline if it meets a particular test condition. Objects that do not pass the test are removed from the pipeline. You supply the test condition as the value of the Where-ObjectFilterScript parameter.
Performing Simple Tests with Where-Object
The value of FilterScript is a script block -  one or more Windows PowerShell commands surrounded by braces {} - that evaluates to true or false. These script blocks can be very simple, but creating them requires knowing about another Windows PowerShell concept, comparison operators.  A comparison operator compares the items that appear on each side of it. Comparison operators begin with a '-' character and are followed by a name. Basic comparison operators work on almost any kind of object. The more advanced comparison operators might only work on text or arrays.
Note: 
By default, when working with text, Windows PowerShell comparison operators are case-insensitive. 
Due to parsing considerations, symbols such as <,>, and = are not used as comparison operators. Instead, comparison operators are comprised of letters. The basic comparison operators are listed in the following table.

Comparison Operator	Meaning	Example (returns true)	
-eq	is equal to	1 -eq 1	
-ne	Is not equal to	1 -ne 2	
-lt	Is less than	1 -lt 2	
-le	Is less than or equal to	1 -le 2	
-gt	Is greater than	2 -gt 1	
-ge	Is greater than or equal to	2 -ge 1	
-like	Is like (wildcard comparison for text)	"file.doc" -like "f*.do?"	
-notlike	Is not like (wildcard comparison for text)	"file.doc" -notlike "p*.doc"	
-contains	Contains	1,2,3 -contains 1	
-notcontains	Does not contain	 1,2,3 -notcontains 4	

Where-Object script blocks use the special variable '$_' to refer to the current object in the pipeline. Here is an example of how it works. If you have a list of numbers, and only want to return the ones that are less than 3, you can use Where-Object to filter the numbers by typing:
PS> 1,2,3,4 | Where-Object -FilterScript {$_ -lt 3}
1
2
Filtering Based on Object Properties
Since $_ refers to the current pipeline object, we can access its properties for our tests.
As an example, we can look at the Win32_SystemDriver class in WMI. There might be hundreds of system drivers on a particular system, but you might only be interested in a particular set of the system drivers, such as those which are currently running. If you use Get-Member to view Win32_SystemDriver members (Get-WmiObject -Class Win32_SystemDriver | Get-Member -MemberType Property) you will see that the relevant property is State, and that it has a value of "Running" when the driver is running. You can filter the system drivers, selecting only the running ones by typing:
Get-WmiObject -Class Win32_SystemDriver | Where-Object -FilterScript {$_.State -eq "Running"}
This still produces a long list. You may want to filter to only select the drivers set to start automatically by testing the StartMode value as well:
PS> Get-WmiObject -Class Win32_SystemDriver | Where-Object -FilterScript {$_.State -eq "Running"} | Where-Object -FilterScript {$_.StartMode -eq "Auto"}

DisplayName : RAS Asynchronous Media Driver
Name        : AsyncMac
State       : Running
Status      : OK
Started     : True

DisplayName : Audio Stub Driver
Name        : audstub
State       : Running
Status      : OK
Started     : True
This gives us a lot of information we no longer need since we know that the drivers are running. In fact, the only information we probably need at this point are the name and the display name. The following command includes only those two properties, resulting in much simpler output:
PS> Get-WmiObject -Class Win32_SystemDriver | Where-Object -FilterScript {$_.State -eq "Running"} | Where-Object -FilterScript {$_.StartMode -eq "Manual"} | Format-Table -Property Name,DisplayName

Name                                    DisplayName
----                                    -----------
AsyncMac                                RAS Asynchronous Media Driver
Fdc                                     Floppy Disk Controller Driver
Flpydisk                                Floppy Disk Driver
Gpc                                     Generic Packet Classifier
IpNat                                   IP Network Address Translator
mouhid                                  Mouse HID Driver
MRxDAV                                  WebDav Client Redirector
mssmbios                                Microsoft System Management BIOS Driver
There are two Where-Object elements in the above command, but they can be expressed in a single Where-Object element by using the -and logical operator, like this:
Get-WmiObject -Class Win32_SystemDriver | Where-Object -FilterScript { ($_.State -eq "Running") -and ($_.StartMode -eq "Manual") } | Format-Table -Property Name,DisplayName
The standard logical operators are listed in the following table.

Logical Operator	Meaning	Example (returns true)	
-and	Logical and; true if both sides are true	(1 -eq 1) -and (2 -eq 2)	
-or	Logical or; true if either side is true	(1 -eq 1) -or (1 -eq 2)	
-not	Logical not; reverses true and false	 -not (1 -eq 2)	
!	Logical not; reverses true and false	!(1 -eq 2)	

Repeating a Task for Multiple Objects (ForEach-Object)
The ForEach-Object cmdlet uses script blocks and the $_ descriptor for the current pipeline object to let you run a command on each object in the pipeline. This can be used to perform some complicated tasks.
One situation where this can be useful is manipulating data to make it more useful. For example, the Win32_LogicalDisk class from WMI can be used to return free space information for each local disk. The data is returned in terms of bytes, however, which makes it difficult to read:
PS> Get-WmiObject -Class Win32_LogicalDisk

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 50665070592
Size         : 203912880128
VolumeName   : Local Disk
We can convert the FreeSpace value to megabytes by dividing each value by 1024 twice; after the first division, the data is in kilobytes, and after the second division it is megabytes. You can do that in a ForEach-Object script block by typing:
Get-WmiObject -Class Win32_LogicalDisk | ForEach-Object -Process {($_.FreeSpace)/1024.0/1024.0}
48318.01171875
Unfortunately, the output is now data with no associated label. Because WMI properties such as this are read-only, you cannot directly convert FreeSpace. If you type this:
Get-WmiObject -Class Win32_LogicalDisk | ForEach-Object -Process {$_.FreeSpace = ($_.FreeSpace)/1024.0/1024.0}
You get an error message:
"FreeSpace" is a ReadOnly property.
At line:1 char:70
+ Get-WmiObject -Class Win32_LogicalDisk | ForEach-Object -Process {$_.F <<<< r
eeSpace = ($_.FreeSpace)/1024.0/1024.0}
You could reorganize the data using some advanced techniques, but a simpler approach is to create a new object, using Select-Object.
Selecting Parts of Objects (Select-Object)
You can use the Select-Object cmdlet to create new, custom Windows PowerShell objects that contain properties selected from the objects you use to create them. Type the following command to create a new object that includes only the Name and FreeSpace properties of the Win32_LogicalDisk WMI class:
PS> Get-WmiObject -Class Win32_LogicalDisk | Select-Object -Property Name,FreeSpace

Name                                    FreeSpace
----                                    ---------
C:                                      50664845312
You can not see the type of data after issuing that command, but if you pipe the result to Get-Member after the Select-Object, you can tell that you have a new type of object, a PSCustomObject:
PS> Get-WmiObject -Class Win32_LogicalDisk | Select-Object -Property Name,FreeSpace| Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       System.Boolean Equals(Object obj)
GetHashCode Method       System.Int32 GetHashCode()
GetType     Method       System.Type GetType()
ToString    Method       System.String ToString()
FreeSpace   NoteProperty  FreeSpace=...
Name        NoteProperty System.String Name=C:
Select-Object has many uses. One of them is replicating data that you can then modify. We can now handle the problem we ran across in the previous section. We can update the value of FreeSpace in our newly-created objects and the output will include the descriptive label:
Get-WmiObject -Class Win32_LogicalDisk | Select-Object -Property Name,FreeSpace | ForEach-Object -Process {$_.FreeSpace = ($_.FreeSpace)/1024.0/1024.0; $_}
Name                                                                  FreeSpace
----                                                                  ---------
C:                                                                48317.7265625
Sorting Objects
We can organize displayed data to make it easier to scan by using the Sort-Object cmdlet. Sort-Object takes the name of one or more properties to sort on, and returns data sorted by the values of those properties.
Consider the problem of listing Win32_SystemDriver instances. If we want to sort by State and then by Name, we can do it by typing:
Get-WmiObject -Class Win32_SystemDriver | Sort-Object -Property State,Name | Format-Table -Property Name,State,Started,DisplayName -AutoSize -Wrap
Although this is a lengthy display, you can see items with the same state grouped together:
Name           State   Started DisplayName
----           -----   ------- -----------
ACPI           Running    True Microsoft ACPI Driver
AFD            Running    True AFD
AmdK7          Running    True AMD K7 Processor Driver
AsyncMac       Running    True RAS Asynchronous Media Driver
...
Abiosdsk       Stopped   False Abiosdsk
ACPIEC         Stopped   False ACPIEC
aec            Stopped   False Microsoft Kernel Acoustic Echo Canceller
...
You can also sort the objects in reverse order by specifying the Descending parameter. This reverses the sort order so that names are sorted in reverse alphabetical order and numbers are sorted by descending size.
PS> Get-WmiObject -Class Win32_SystemDriver | Sort-Object -Property State,Name -Descending | Format-Table -Property Name,State,Started,DisplayName -AutoSize -Wrap

Name           State   Started DisplayName
----           -----   ------- -----------
WS2IFSL        Stopped   False Windows Socket 2.0 Non-IFS Service Provider Supp
                               ort Environment
wceusbsh       Stopped   False Windows CE USB Serial Host Driver...
...
wdmaud         Running    True Microsoft WINMM WDM Audio Compatibility Driver
Wanarp         Running    True Remote Access IP ARP Driver
...
Using Variables to Store Objects
Windows PowerShell works with objects. Windows PowerShell lets you create variables - essentially named objects - to preserve output to use later. If you are used to working with variables in other shells, remember that Windows PowerShell variables are objects, not text.
Variables are always specified with the initial character $, and can include any alphanumeric characters or the underscore in their names.
Creating a Variable
You can create a variable by typing a valid variable name:
PS> $loc
PS>
This returns no result because $loc does not have a value. You can create a variable and assign it a value in the same step. Windows PowerShell only creates the variable if it does not exist; otherwise, it assigns the specified value to the existing variable. To store your current location in the variable $loc, type:
$loc = Get-Location
There is no output displayed when you type this command because the output is sent to $loc. In Windows PowerShell, displayed output is a side effect of the fact that data which is not otherwise directed always gets sent to the screen. Typing $loc will show your current location:
PS> $loc

Path
----
C:\temp
You can use Get-Member to display information about the contents of variables. Piping $loc to Get-Member will show you that it is a PathInfo object, just like the output from Get-Location:
PS> $loc | Get-Member -MemberType Property

   TypeName: System.Management.Automation.PathInfo

Name         MemberType Definition
----         ---------- ----------
Drive        Property   System.Management.Automation.PSDriveInfo Drive {get;}
Path         Property   System.String Path {get;}
Provider     Property   System.Management.Automation.ProviderInfo Provider {...
ProviderPath Property   System.String ProviderPath {get;}
Manipulating Variables
Windows PowerShell provides several commands to manipulate variables. You can see a complete listing in a readable form by typing:
Get-Command -Noun Variable | Format-Table -Property Name,Definition -AutoSize -Wrap
In addition to the variables you create in your current Windows PowerShell session, there are several system-defined variables. You can use the Remove-Variable cmdlet to clear out all of the variables which are not controlled by Windows PowerShell. Type the following command to clear all variables:
Remove-Variable -Name * -Force -ErrorAction SilentlyContinue
This will produce the confirmation prompt you see below.
Confirm
Are you sure you want to perform this action?
Performing operation "Remove Variable" on Target "Name: Error".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):A
If you then run the Get-Variable cmdlet, you will see the remaining Windows PowerShell variables. Since there is also a variable Windows PowerShell drive, you can also display all Windows PowerShell variables by typing:
Get-ChildItem variable:
Using Cmd.exe Variables
Although Windows PowerShell is not Cmd.exe, it runs in a command shell environment and can use the same variables available in any environment in Windows. These variables are exposed through a drive named env:. You can view these variables by typing:
Get-ChildItem env:
Although the standard variable cmdlets are not designed to work with env: variables, you can still use them by specifying the env: prefix. For example, to see the operating system root directory, you can use the command shell %SystemRoot% variable from within Windows PowerShell by typing:
PS> $env:SystemRoot
C:\WINDOWS
You can also create and modify environment variables from within Windows PowerShell. Environment variables accessed from Windows PowerShell conform to the normal rules for environment variables elsewhere in Windows.
Using Windows PowerShell for Administration
The fundamental goal of Windows PowerShell is providing better, easier administrative control over systems, either interactively or from script. This chapter walks through solutions to many specific problems in administering Windows systems with Windows PowerShell. Although we have not talked about scripts or functions in the Windows PowerShell Primer, the solutions can be used from scripts or as functions later. We will show examples that include functions as part of the solution to solve problems.
Throughout the solution descriptions, you will see a mix of solutions using specific cmdlets, the general Get-WmiObject cmdlet, and even external tools that are part of the Windows and .NET infrastructures. Use of external tools is part of the long-term design intent of Windows PowerShell. Even as the system grows, users will continually encounter situations in which the available toolsets do not do everything they need. Rather than foster dependency on cmdlet implementations alone, Windows PowerShell tries to support integrating solutions from every possible alternative scenario.
Managing Local Processes
There are only two core Process cmdlets: Get-Process and Stop-Process. Because it is possible to inspect and filter processes using either parameters or the Object cmdlets, you can perform some complex tasks using only these two cmdlets.
Listing Processes (Get-Process)
You can get a list of all processes running on the local system by running Get-Process with no parameters.
You can also return a single process by specifying the ProcessId using the Id parameter. The following example will return the system idle process:
PS> Get-Process -Id 0
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
      0       0        0         16     0               0 Idle
Although it is normal for cmdlets to return no data in some situations, when you specify a process by its ProcessId, Get-Process generates an error if it finds no matches, because the usual intent is to retrieve a known running process. If there is no process with that Id, it is likely that the Id is incorrect or that the process of interest has already exited:
PS> Get-Process -Id 99
Get-Process : No process with process ID 99 was found.
At line:1 char:12
+ Get-Process  <<<< -Id 99
The Name parameter can be used to specify a subset of processes based on the process name. Because processes can have the same name, the output might include more than one process. If there is no process with that name, Get-Process will return an error as it does when you specify a ProcessId. For example, if you specify the process name explore instead of explorer:
PS> Get-Process -Name explore
Get-Process : No process with process name 'explore' was found.
At line:1 char:12
+ Get-Process  <<<< -Name explore
The Name parameter supports the use of wildcards, so you can type the first few characters of a name followed by an asterisk to get a listing:
PS> Get-Process -Name ex*
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    234       7     5572      12484   134     2.98   1684 EXCEL
    555      15    34500      12384   134   105.25    728 explorer
Note
·	Because the .NET System.Diagnostics.Process class is the foundation for Windows PowerShell processes, it follows some of the conventions used by System.Diagnostics.Process. One of those conventions is that the process name for an executable never includes the ".exe" at the end of the executable name.
Get-Process will also accept multiple values for the Name parameter. Just as with specifying a single name, you will see an error if a name cannot be matched, although you also get the normal output for matching processes:
PS> Get-Process -Name exp*,power*,NotAProcess
Get-Process : No process with process name 'NotAProcess' was found.
At line:1 char:12
+ Get-Process  <<<< -Name exp*,power*,svchost,NotAProcess
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    540      15    35172      48148   141    88.44    408 explorer
    605       9    30668      29800   155     7.11   3052 powershell
Stopping Processes (Stop-Process)
Windows PowerShell gives you flexibility for listing processes, but what about stopping a process?
The Stop-Process cmdlet takes a Name or Id to specify a process you wish to stop. Your ability to stop processes depends on your permissions. Some processes cannot be stopped. For example, if you try to stop the idle process, you get an error:
PS> Stop-Process -Name Idle
Stop-Process : Process 'Idle (0)' cannot be stopped due to the following error:
 Access is denied
At line:1 char:13
+ Stop-Process  <<<< -Name Idle
You can also force prompting with the Confirm parameter. This parameter is particularly useful if you use a wildcard when specifying the process name, because you may accidentally match some processes you do not want to stop:
PS> Stop-Process -Name t*,e* -Confirm
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Process" on Target "explorer (408)".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):n
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Process" on Target "taskmgr (4072)".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):n
Complex process manipulation is possible using some of the object filtering cmdlets. Because a Process object has a Responding property that is true when it is no longer responding, you can stop all nonresponsive applications with the following command:
Get-Process | Where-Object -FilterScript {$_.Responding -eq $false} | Stop-Process
You can use the same approach in other situations. For example, suppose a secondary system tray application automatically runs when users start another application. You may find that this does not work correctly in Terminal Services sessions, but you still want to keep it in sessions run on the physical computer console. Sessions connected to the physical computer desktop always have a session ID of 0, so you can stop all instances of the process that are in other sessions using Where-Object and the process, SessionId:
Get-Process -Name BadApp | Where-Object -FilterScript {$_.SessionId -neq 0} | Stop-Process
Stopping All Other Windows PowerShell Sessions
It may occasionally be useful to be able to stop all running Windows PowerShell sessions other than the current session. If a session is using too many resources or is inaccessible (it may be running remotely or in another desktop session), you may not be able to directly stop it. If you try to stop all running sessions, however, the current session may be terminated instead.
Each Windows PowerShell session has an environment variable PID that contains the Id of the Windows PowerShell process. You can check the $PID against the Id of each session and terminate only Windows PowerShell sessions that have a different Id. The following pipeline command does this and returns the list of terminated sessions (because of the use of the PassThru parameter):
PS> Get-Process -Name powershell | Where-Object -FilterScript {$_.Id -ne $PID} | Stop-Process -
PassThru
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    334       9    23348      29136   143     1.03    388 powershell
    304       9    23152      29040   143     1.03    632 powershell
    302       9    20916      26804   143     1.03   1116 powershell
    335       9    25656      31412   143     1.09   3452 powershell
    303       9    23156      29044   143     1.05   3608 powershell
    287       9    21044      26928   143     1.02   3672 powershell
Managing Local Services
There are eight core Service cmdlets, designed for a wide range of service tasks . We will look only at listing and changing running state for services, but you can get a list Service cmdlets by using Get-Help *-Service, and you can find information about each Service cmdlet by using Get-Help<Cmdlet-Name>, such as Get-Help New-Service. 
Listing Services
You can enumerate the local services on a computer by using Get-Service. As with Get-Process, using the Get-Service command without parameters returns all services. You can filter by name, even using an asterisk as a wildcard:
PS> Get-Service -Name se*
Status   Name               DisplayName
------   ----               -----------
Running  seclogon           Secondary Logon
Running  SENS               System Event Notification
Stopped  ServiceLayer       ServiceLayer
Because it is not always obvious what the real name for the service is, you may find you need to find services by display name. You can do this by specific name, using wildcards, or using a list of display names:
PS> Get-Service -DisplayName se*
Status   Name               DisplayName
------   ----               -----------
Running  lanmanserver       Server
Running  SamSs              Security Accounts Manager
Running  seclogon           Secondary Logon
Stopped  ServiceLayer       ServiceLayer
Running  wscsvc             Security Center
PS> Get-Service -DisplayName ServiceLayer,Server
Status   Name               DisplayName
------   ----               -----------
Running  lanmanserver       Server
Stopped  ServiceLayer       ServiceLayer
Stopping, Starting, Suspending, and Restarting Services
The Service cmdlets all have the same general form.Services can be specified by common name or display name, and take lists and wildcards as values. To stop the print spooler, use:
Stop-Service -Name spooler
To start the print spooler after it is stopped, use:
Start-Service -Name spooler
To suspend the print spooler, use:
Suspend-Service -Name spooler
The Restart-Service cmdlet works in the same manner as the other Service cmdlets, but we will show some more complex examples for it. In the simplest use, you specify the name of the service:
PS> Restart-Service -Name spooler
WARNING: Waiting for service 'Print Spooler (Spooler)' to finish starting...
WARNING: Waiting for service 'Print Spooler (Spooler)' to finish starting...
PS>
You will notice that you get a repeated warning message about the Print Spooler starting up. When you perform a service operation that takes some time, Windows PowerShell will notify you that it is still attempting to perform the task.
If you want to restart multiple services, you can get a list of services, filter them, and then perform the restart:
PS> Get-Service | Where-Object -FilterScript {$_.CanStop} | Restart-Service
WARNING: Waiting for service 'Computer Browser (Browser)' to finish stopping...
WARNING: Waiting for service 'Computer Browser (Browser)' to finish stopping...
Restart-Service : Cannot stop service 'Logical Disk Manager (dmserver)' because
 it has dependent services. It can only be stopped if the Force flag is set.
At line:1 char:57
+ Get-Service | Where-Object -FilterScript {$_.CanStop} | Restart-Service <<<<
WARNING: Waiting for service 'Print Spooler (Spooler)' to finish starting...
WARNING: Waiting for service 'Print Spooler (Spooler)' to finish starting...
Collecting Information About Computers
Get-WmiObject is the most important cmdlet for general system management tasks. All critical subsystem settings are exposed via WMI. Furthermore, WMI treats data as objects that are in collections of one or more items. Because Windows PowerShell also works with objects and has a pipeline that allows you to treat single or multiple objects in the same way, generic WMI access allows you to perform some advanced tasks with very little work.
The following examples demonstrate how to collect specific information by using Get-WmiObject against an arbitrary computer. We specify the ComputerName parameter with the dot value (.), which represents the local computer. You can specify a name or IP address associated with any computer you can reach via WMI. To retrieve information about the local computer, you could omit the -ComputerName .
Listing Desktop Settings
We'll begin with a command that collects information about the desktops on the local computer.  
Get-WmiObject -Class Win32_Desktop -ComputerName .
This returns information for all desktops, whether they are in use or not.
Note: 
Information returned by some WMI classes can be very detailed, and often include metadata about the WMI class. Because most of these metadata properties have names that begin with a double-underscore, you can filter the properties using Select-Object. Specify only properties that begin with alphabetic characters by using [a-z]* as the Property value. For example:
Get-WmiObject -Class Win32_Desktop -ComputerName . | Select-Object -Property [a-z]*
To filter out the metadata, use a pipeline operator (|) to send the results of the Get-WmiObject command to Select-Object -Property [a-z]*.
Listing BIOS Information
The WMI Win32_BIOS class returns fairly compact and complete information about the system BIOS on the local computer:
Get-WmiObject -Class Win32_BIOS -ComputerName .
Listing Processor Information
You can retrieve general processor information using WMI's Win32_Processor class, although you will likely want to filter the information:
Get-WmiObject -Class Win32_Processor -ComputerName . | Select-Object -Property [a-z]*
For a generic description string of the processor family, you can just return the Win32_ComputerSystemSystemType property:
PS> Get-WmiObject -Class Win32_ComputerSystem -ComputerName . | Select-Object -Property SystemType
SystemType
----------
X86-based PC
Listing Computer Manufacturer and Model
Computer model information is also available from Win32_ComputerSystem. The standard displayed output will not need any filtering to provide OEM data:
PS> Get-WmiObject -Class Win32_ComputerSystem
Domain              : WORKGROUP
Manufacturer        : Compaq Presario 06
Model               : DA243A-ABA 6415cl NA910
Name                : MyPC
PrimaryOwnerName    : Jane Doe
TotalPhysicalMemory : 804765696
Your output from commands such as this, which return information directly from some hardware, is only as good as the data you have. Some information is not correctly configured by hardware manufacturers and may therefore be unavailable.
Listing Installed Hotfixes
You can list all installed hotfixes by using Win32_QuickFixEngineering:
Get-WmiObject -Class Win32_QuickFixEngineering -ComputerName .
This class returns a list of hotfixes that looks like this:
Description         : Update for Windows XP (KB910437)
FixComments         : Update
HotFixID            : KB910437
Install Date        :
InstalledBy         : Administrator
InstalledOn         : 12/16/2005
Name                :
ServicePackInEffect : SP3
Status              :
For more succinct output, you may want to exclude some properties. Although you can use the Get-WmiObject Property parameter to choose only the HotFixID, doing so will actually return more information, because all of the metadata is displayed by default:
PS> Get-WmiObject -Class Win32_QuickFixEngineering -ComputerName . -Property HotFixId
HotFixID         : KB910437
__GENUS          : 2
__CLASS          : Win32_QuickFixEngineering
__SUPERCLASS     :
__DYNASTY        :
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
The additional data is returned, because the Property parameter in Get-WmiObject restricts the properties returned from WMI class instances, not the object returned to Windows PowerShell. To reduce the output, use Select-Object:
PS> Get-WmiObject -Class Win32_QuickFixEngineering -ComputerName . -Property Hot
FixId | Select-Object -Property HotFixId
HotFixId
--------
KB910437
Listing Operating System Version Information
The Win32_OperatingSystem class properties include version and service pack information. You can explicitly select only these properties to get a version information summary from Win32_OperatingSystem:  
Get-WmiObject -Class Win32_OperatingSystem -ComputerName . | Select-Object -Property BuildNumber,BuildType,OSType,ServicePackMajorVersion,ServicePackMinorVersion
You can also use wildcards with the Select-Object Property parameter. Because all of the properties beginning with either Build or ServicePack are important to use here, we can shorten this to the following form:
PS> Get-WmiObject -Class Win32_OperatingSystem -ComputerName . | Select-Object -Property Build*,OSType,ServicePack*

BuildNumber             : 2600
BuildType               : Uniprocessor Free
OSType                  : 18
ServicePackMajorVersion : 2
ServicePackMinorVersion : 0
Listing Local Users and Owner
Local general user information—number of licensed users, current number of users, and owner name—can be found with a selection of Win32_OperatingSystem properties. You can explicitly select the properties to display like this:
Get-WmiObject -Class Win32_OperatingSystem -ComputerName . | Select-Object -Property NumberOfLicensedUsers,NumberOfUsers,RegisteredUser
A more succinct version using wildcards is:  
Get-WmiObject -Class Win32_OperatingSystem -ComputerName . | Select-Object -Property *user*
Getting Available Disk Space
To see the disk space and free space for local drives, you can use the WMI Win32_LogicalDisk class. You need to see only instances with a DriveType of 3—the value WMI uses for fixed hard disks.
Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" -ComputerName .

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 65541357568
Size         : 203912880128
VolumeName   : Local Disk

DeviceID     : Q:
DriveType    : 3
ProviderName :
FreeSpace    : 44298250240
Size         : 122934034432
VolumeName   : New Volume

PS> Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" -ComputerName . | Measure-Object -Property FreeSpace,Size -Sum

Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" -ComputerName . | Measure-Object -Property FreeSpace,Size -Sum | Select-Object -Property Property,Sum
Getting Logon Session Information
You can get general information about logon sessions associated with users through the WMI Win32_LogonSession class:  
Get-WmiObject -Class Win32_LogonSession -ComputerName .
Getting the User Logged on to a Computer
You can display the user logged on to a particular computer system using Win32_ComputerSystem. This command returns only the user logged on to the system desktop:
Get-WmiObject -Class Win32_ComputerSystem -Property UserName -ComputerName .
Getting Local Time from a Computer
You can retrieve the current local time on a specific computer using the WMI Win32_LocalTime class. Because this class by default displays all metadata, you may want to filter it using Select-Object:
PS> Get-WmiObject -Class Win32_LocalTime -ComputerName . | Select-Object -Property [a-z]*

Day          : 15
DayOfWeek    : 4
Hour         : 12
Milliseconds :
Minute       : 11
Month        : 6
Quarter      : 2
Second       : 52
WeekInMonth  : 3
Year         : 2006
Displaying Service Status
To view the status of all services on a specific computer, you can locally use the Get-Service cmdlet as mentioned earlier. For remote systems, you can use the WMI Win32_Service class. If you also use Select-Object to filter the results to Status, Name, and DisplayName, the output format will be almost identical to that from Get-Service:
Get-WmiObject -Class Win32_Service -ComputerName . | Select-Object -Property Status,Name,DisplayName
To allow the complete display of names for the occasional services with extremely long names, you may want to use Format-Table with the AutoSize and Wrap parameters, to optimize column width and allow long names to wrap instead of being truncated:
Get-WmiObject -Class Win32_Service -ComputerName . | Format-Table -Property Status,Name,DisplayName -AutoSize -Wrap
Working with Software Installations
Applications that are designed to use Windows Installer can be accessed through WMI's Win32_Product class, but not all applications in use today use the Windows Installer. Because the Windows Installer provides the widest range of standard techniques for working with installable applications, we will focus primarily on those applications. Applications that use alternate setup routines will generally not be managed by the Windows Installer. Specific techniques for working with those applications will depend on the installer software and decisions made by the application developer.
Note: 
Applications that are installed by copying the application files to the computer usually cannot be managed by using techniques discussed here. You can manage these applications as files and folders by using the techniques discussed in the "Working With Files and Folders" section.
Listing Windows Installer Applications
To list the applications installed with the Windows Installer on a local or remote system, use the following simple WMI query:
PS> Get-WmiObject -Class Win32_Product -ComputerName .
IdentifyingNumber : {7131646D-CD3C-40F4-97B9-CD9E4E6262EF}
Name              : Microsoft .NET Framework 2.0
Vendor            : Microsoft Corporation
Version           : 2.0.50727
Caption           : Microsoft .NET Framework 2.0
To display all of the properties of the Win32_Product object to the display, use the Properties parameter of the formatting cmdlets, such as the Format-List cmdlet, with a value of * (all). 
PS> Get-WmiObject -Class Win32_Product -ComputerName . | Where-Object -FilterScript {$_.Name -eq "Microsoft .NET Framework 2.0"} | Format-List -Property *
Name              : Microsoft .NET Framework 2.0
Version           : 2.0.50727
InstallState      : 5
Caption           : Microsoft .NET Framework 2.0
Description       : Microsoft .NET Framework 2.0
IdentifyingNumber : {7131646D-CD3C-40F4-97B9-CD9E4E6262EF}
InstallDate       : 20060506
InstallDate2      : 20060506000000.000000-000
InstallLocation   :
PackageCache      : C:\WINDOWS\Installer\619ab2.msi
SKUNumber         :
Vendor            : Microsoft Corporation
Or, you could use the Get-WmiObject Filter parameter to select only Microsoft .NET Framework 2.0. Because the filter used in this command is a WMI filter, it uses WMI Query Language (WQL) syntax, not Windows PowerShell syntax. Instead,:
Get-WmiObject -Class Win32_Product -ComputerName . -Filter "Name='Microsoft .NET Framework 2.0'"| Format-List -Property *
Note
·	WQL queries frequently use characters, such as spaces or equal signs, that have a special meaning in Windows PowerShell. For this reason, it is prudent to always enclose the value of the Filter parameter in quotation marks. You can also use the Windows PowerShell escape character, a backtick (`), although it may not improve readability. The following command is equivalent to the previous command and returns the same results, but uses the backtick to escape special characters, instead of quoting the entire filter string:
·	Get-WmiObject -Class Win32_Product -ComputerName . -Filter Name`=`'Microsoft` .NET` Framework` 2.0`' | Format-List -Property *
To list only the properties that interest you, use the Property parameter of the formatting cmdlets to list the desired properties.
Get-WmiObject -Class Win32_Product -ComputerName . | Format-List -Property Name,InstallDate,InstallLocation,PackageCache,Vendor,Version,IdentifyingNumber
...
Name              : HighMAT Extension to Microsoft Windows XP CD Writing Wizard
InstallDate       : 20051022
InstallLocation   : C:\Program Files\HighMAT CD Writing Wizard\
PackageCache      : C:\WINDOWS\Installer\113b54.msi
Vendor            : Microsoft Corporation
Version           : 1.1.1905.1
IdentifyingNumber : {FCE65C4E-B0E8-4FBD-AD16-EDCBE6CD591F}
...
Finally, to find only the names of installed applications, a simple Format-Wide statement simplifies the output:
Get-WmiObject -Class Win32_Product -ComputerName .  | Format-Wide -Column 1
Although we now have several ways to look at applications that used the Windows Installer for installation, we have not considered other applications. Because most standard applications register their uninstaller with Windows, we can work with those locally by finding them in the Windows registry. 
Listing All Uninstallable Applications
Although there is no guaranteed way to find every application on a system, it is possible to find all programs with listings displayed in the Add or Remove Programs dialog box. Add or Remove Programs finds these applications in the following registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall. 
We can also examine this key to find applications. To make it easier to view the Uninstall key, we can map a Windows PowerShell drive to this registry location:
PS>    

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
Uninstall  Registry      HKEY_LOCAL_MACHINE\SOFTWARE\Micr...
Note
·	The HKLM: drive is mapped to the root of HKEY_LOCAL_MACHINE, so we used that drive in the path to the Uninstall key. Instead of HKLM: we could have specified the registry path by using either HKLM or HKEY_LOCAL_MACHINE. The advantage of using an existing registry drive is that we can use tab-completion to fill in the keys names, so we do not need to type them.
We now have a drive named "Uninstall" that can be used to quickly and conveniently look for application installations. We can find the number of installed applications by counting the number of registry keys in the Uninstall: Windows PowerShell drive:
PS> (Get-ChildItem -Path Uninstall:).Count
459
We can search this list of applications further by using a variety of techniques, beginning with Get-ChildItem. To get a list of applications and save them in the $UninstallableApplications variable, use the following command:
$UninstallableApplications = Get-ChildItem -Path Uninstall:
Note
·	We are using a lengthy variable name here for clarity. In actual use, there is no reason to use long names. Although you can use tab-completion for variable names, you can also use 1–2 character names for speed. Longer, descriptive names are most useful when you are developing code for reuse.
To display the values of the registry entries in the registry keys under Uninstall, use the GetValue method of the registry keys. The value of the method is the name of the registry entry.
For example, to find the display names of applications in the Uninstall key, use the following command:
PS> Get-ChildItem -Path Uninstall: | ForEach-Object -Process { $_.GetValue("DisplayName") }
There is no guarantee that these values are unique. In the following example, two installed items appear as "Windows Media Encoder 9 Series":
PS> Get-ChildItem -Path Uninstall: | Where-Object -FilterScript { $_.GetValue("DisplayName") -eq "Windows Media Encoder 9 Series"}

   Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Micros
oft\Windows\CurrentVersion\Uninstall

SKC  VC Name                           Property
---  -- ----                           --------
  0   3 Windows Media Encoder 9        {DisplayName, DisplayIcon, UninstallS...
  0  24 {E38C00D0-A68B-4318-A8A6-F7... {AuthorizedCDFPrefix, Comments, Conta...
Installing Applications
You can use the Win32_Product class to install Windows Installer packages, remotely or locally. When installing remotely, use a Universal Naming Convention (UNC) network path to specify the path to the .msi package, because the WMI subsystem does not understand Windows PowerShell paths. For example, to install the MSI package NewPackage.msi located in the network share \\AppServ\dsp on the remote computer PC01, type the following command at the Windows PowerShell prompt:
(Get-WMIObject -ComputerName PC01 -List | Where-Object -FilterScript {$_.Name -eq "Win32_Product"}).Install(\\AppSrv\dsp\NewPackage.msi)
Applications that do not use Windows Installer technology may have application-specific methods available for automated deployment. To determine whether there is a method for deployment automation, check the documentation for the application or consult the application vendor's support system. In some cases, even if the application vendor did not specifically design the application for installation automation, the installer software manufacturer may have some techniques for automation.
Removing Applications
Removing a Windows Installer package using Windows PowerShell works in approximately the same way as installing a package. Here is an example that selects the package to uninstall based on its name; in some cases it may be easier to filter with the IdentifyingNumber:
(Get-WmiObject -Class Win32_Product -Filter "Name='ILMerge'" -ComputerName . ).Uninstall()
Removing other applications is not quite so simple, even when done locally. We can find the command line uninstallation strings for these applications by extracting the UninstallString property. This method works for Windows Installer applications and for older programs appearing under the Uninstall key:
Get-ChildItem -Path Uninstall: | ForEach-Object -Process { $_.GetValue("UninstallString") }
You can filter the output by the display name, if you like:
Get-ChildItem -Path Uninstall: | Where-Object -FilterScript { $_.GetValue("DisplayName") -like "Win*"} | ForEach-Object -Process { $_.GetValue("UninstallString") }
However, these strings may not be directly usable from the Windows PowerShell prompt without some modification.
Upgrading Windows Installer Applications
To upgrade an application,you need to know the name of the application and the path to the application upgrade package. With that information, you can upgrade an application with a single Windows PowerShell command:
(Get-WmiObject -Class Win32_Product -ComputerName . -Filter "Name='OldAppName'").Upgrade(\\AppSrv\dsp\OldAppUpgrade.msi)
Changing Computer State: Locking, Logging Off, Shutting Down, and Rebooting
To reset a computer in Windows PowerShell, use either a standard command-line tool or a WMI class. Although you are using Windows PowerShell only to run the tool, learning how to change a computer's power state in Windows PowerShell illustrates some of the important details about working with external tools in the shell.
Locking a Computer
The only way to lock a computer directly with the standard available tools is to call the LockWorkstation() function in user32.dll:
rundll32.exe user32.dll,LockWorkStation
This command immediately locks the workstation. It uses rundll32.exe, which runs Windows DLLs (and saves their libraries for repeated use) to run user32.dll, a library of Windows management functions. 
When you lock a workstation while Fast User Switching is enabled, such as on Windows XP, the computer displays the user logon screen rather than starting the current user's screensaver. 
To shut down particular sessions on a Terminal Server, use the tsshutdn.exe command line tool.

Logging Off the Current Session
You can use several different techniques to log off of a session on the local system. The simplest way is to use the Remote Desktop/Terminal Services command line tool, logoff.exe (For details, at the Windows PowerShell prompt, type logoff /?). To log off the current active session, type logoff with no arguments.
You can also use the shutdown.exe tool with its logoff option:
shutdown.exe -l
A third option is to use WMI. The Win32_OperatingSystem class has a Win32Shutdown method. Invoking the method with the 0 flag initiates logoff:
(Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).Win32Shutdown(0)
For more information, and to find other features of the Win32Shutdown method, see "Win32Shutdown Method of the Win32_OperatingSystem Class" in MSDN. 
Shutting Down or Rebooting a Computer
Shutting down and rebooting computers are generally the same types of tasks. Tools that shut down a computer will generally reboot it as well—and vice versa. There are two straightforward options for rebooting a computer from Windows PowerShell. Use either tsshutdn.exe or shutdown.exe with appropriate arguments. You can get detailed usage information from tsshutdn.exe /? or shutdown.exe /?.
You can also perform shutdown and reboot operations using Win32_OperatingSystem directly from Windows PowerShell as well. 
To shut down the computer, use the Win32Shutdown method with the 1 flag.
(Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).Win32Shutdown(1)

To reboot the operating system, use the Win32Shutdown method with the 2 flag.
(Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).Win32Shutdown(2)

Working with Printers
You can use Windows PowerShell to manage printers by using WMI and the WScript.Network COM object from WSH. We will use a mix of both tools to demonstrate specific tasks.
Listing Printer Connections
The simplest way to list the printers installed on a computer is to use the WMI Win32_Printer class:
Get-WmiObject -Class Win32_Printer -ComputerName .
You can also list the printers by using the WScript.Network COM object that is typically used in WSH scripts:
(New-Object -ComObject WScript.Network).EnumPrinterConnections()
Because this command returns a simple string collection of port names and printer device names without any distinguishing labels, it is not easy to interpret. 
Adding a Network Printer
To add a new network printer, use WScript.Network:
(New-Object -ComObject WScript.Network).AddWindowsPrinterConnection("\\Printserver01\Xerox5")
Setting a Default Printer
To use WMI to set the default printer, find the printer in the the Win32_Printer collection and then invoke the SetDefaultPrinter method:
(Get-WmiObject -ComputerName . -Class Win32_Printer -Filter "Name='HP LaserJet 5Si'").SetDefaultPrinter()
WScript.Network is a little simpler to use, because it has a SetDefaultPrinter method that takes only the printer name as an argument:
(New-Object -ComObject WScript.Network).SetDefaultPrinter('HP LaserJet 5Si')
Removing a Printer Connection
To remove a printer connection, use the WScript.Network RemovePrinterConnection method:
(New-Object -ComObject WScript.Network).RemovePrinterConnection("\\Printserver01\Xerox5")
Performing Networking Tasks
Because TCP/IP is the most commonly used network protocol, most low-level network protocol administration tasks involve TCP/IP.. In this section, we use Windows PowerShell and WMI to do these tasks.
Listing IP Addresses for a Computer
To get all IP addresses in use on the local computer, use the following command: 
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName . | Format-Table -Property IPAddress
The output of this command differs from most property lists, because values are enclosed in braces:
IPAddress
---------
{192.168.1.80}
{192.168.148.1}
{192.168.171.1}
{0.0.0.0}
To understand why the braces appear, use the Get-Member cmdlet to examine the IPAddress property:
PS> Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName . | Get-Member -Name IPAddress

   TypeName: System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter
Configuration

Name      MemberType Definition
----      ---------- ----------
IPAddress Property   System.String[] IPAddress {get;}
The IPAddress property for each network adapter is actually an array. The braces in the definition indicate that IPAddress is not a System.String value, but an array of System.String values.
Listing IP Configuration Data
To display detailed IP configuration data for each network adapter, use the following command:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName .
The default display for the network adapter configuration object is a very reduced set of the available information. For in-depth inspection and troubleshooting, use Select-Object or a formatting cmdlet, such as Format-List, to specify the properties to be displayed. 
If you are not interested in IPX or WINS properties—probably the case in a modern TCP/IP network—you can use the ExcludeProperty parameter of Select-Object to hide properties with names that begin with "WINS" or "IPX:"
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName . | Select-Object -Property [a-z]* -ExcludeProperty IPX*,WINS*
This command returns detailed information about DHCP, DNS, routing, and other minor IP configuration properties.
Pinging Computers
You can perform a simple ping against a computer using Win32_PingStatus. The following command performs the ping, but returns lengthy output:
Get-WmiObject -Class Win32_PingStatus -Filter "Address='127.0.0.1'" -ComputerName .
A more useful form for summary information a display of the Address, ResponseTime, and StatusCode properties, as generated by the following command. The Autosize parameter of Format-Table resizes the table columns so that they      display properly in the console.
PS> Get-WmiObject -Class Win32_PingStatus -Filter "Address='127.0.0.1'" -ComputerName . | Format-Table -Property Address,ResponseTime,StatusCode -Autosize

Address   ResponseTime StatusCode
-------   ------------ ----------
127.0.0.1            0          0
A status code of 0 indicates a successful ping.
You can use an array to ping multiple computers with a single command. Because there is more than one address, use the ForEach-Object to ping each address separately:
"127.0.0.1","localhost","research.microsoft.com" | ForEach-Object -Process {Get-WmiObject -Class Win32_PingStatus -Filter ("Address='" + $_ + "'") -ComputerName .} | Select-Object -Property Address,ResponseTime,StatusCode
You can use the same command format to ping all of the computers on a subnet, such as a private network that uses network number 192.168.1.0 and a standard Class C subnet mask (255.255.255.0)., Only addresses in the range of 192.168.1.1 through 192.168.1.254 are legitimate local addresses (0 is always reserved for the network number and 255 is a subnet broadcast address).
To represent an array of the numbers from 1 through 254 in Windows PowerShell, use the statement 1..254. A complete subnet ping can be performed by generating the array and then adding the values onto a partial address in the ping statement:
1..254| ForEach-Object -Process {Get-WmiObject -Class Win32_PingStatus -Filter ("Address='192.168.1." + $_ + "'") -ComputerName .} | Select-Object -Property Address,ResponseTime,StatusCode
Note
·	This technique for generating a range of addresses can be used elsewhere as well. You can generate a complete set of addresses in this way:
·	$ips = 1..254 | ForEach-Object -Process {"192.168.1." + $_}
Retrieving Network Adapter Properties
Earlier in this primer, we mentioned that you could retrieve general configuration properties by using Win32_NetworkAdapterConfiguration. Although not strictly TCP/IP information, network adapter information such as MAC addresses and adapter types can be useful for understanding what is going on with a computer. To get a summary of this information, use the following command:
Get-WmiObject -Class Win32_NetworkAdapter -ComputerName .
Assigning the DNS Domain for a Network Adapter
To assigning the DNS domain for automatic name resolution, use the Win32_NetworkAdapterConfiguration SetDNSDomain method. Because you assign the DNS domain for each network adapter configuration independently, you need to use a ForEach-Object statement to assign the domain to each adapter:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=true -ComputerName . | ForEach-Object -Process { $_. SetDNSDomain("fabrikam.com") }
The filtering statement "IPEnabled=true" is necessary, because even on a network that uses only TCP/IP, several of the network adapter configurations on a computer are not true TCP/IP adapters; they are general software elements supporting RAS, PPTP, QoS, and other services for all adapters and thus do not have an address of their own.
You can filter the command by using the Where-Object cmdlet, instead of using the Get-WmiObject filter.
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName . | Where-Object -FilterScript {$_.IPEnabled} | ForEach-Object -Process {$_.SetDNSDomain("fabrikam.com")}
Performing DHCP Configuration Tasks
Modifying DHCP details involves working with a set of network adapters, just as the DNS configuration does. There are several distinct actions you can perform using WMI, and we will step through a few of the common ones.
Determining DHCP-Enabled Adapters
To find the DHCP-enabled adapters on a computer, use the following command:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "DHCPEnabled=true" -ComputerName .
To exclude adapters with IP configuration problems, you can retrieve only IP-enabled adapters:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled=true and DHCPEnabled=true" -ComputerName .
Retrieving DHCP Properties
Because DHCP-related properties for an adapter generally begin with "DHCP," you can use the Property parameter of Format-Table to display only those properties:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "DHCPEnabled=true" -ComputerName . | Format-Table -Property DHCP*
Enabling DHCP on Each Adapter
To enable DHCP on all adapters, use the following command
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=true -ComputerName . | ForEach-Object -Process {$_.EnableDHCP()}
You can use the Filter statement "IPEnabled=true and DHCPEnabled=false" to avoid enabling DHCP where it is already enabled, but omitting this step will not cause errors.
Releasing and Renewing DHCP Leases on Specific Adapters
The Win32_NetworkAdapterConfiguration class has ReleaseDHCPLease and RenewDHCPLease methods. Both are used in the same way. In general, use these methods if you only need to release or renew addresses for an adapter on a specific subnet. The easiest way to filter adapters on a subnet is to choose only the adapter configurations that use the gateway for that subnet. For example, the following command releases all DHCP leases on adapters on the local computer that are obtaining DHCP leases from 192.168.1.254:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled=true and DHCPEnabled=true" -ComputerName . | Where-Object -FilterScript {$_.DHCPServer -contains "192.168.1.254"} | ForEach-Object -Process {$_.ReleaseDHCPLease()}
The only change for renewing a DHCP lease is to use the RenewDHCPLease method instead of the ReleaseDHCPLease method:
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled=true and DHCPEnabled=true" -ComputerName . | Where-Object -FilterScript {$_.DHCPServer -contains "192.168.1.254"} | ForEach-Object -Process {$_.ReleaseDHCPLease()}
Note: 
When using these methods on a remote computer, be aware that you can lose access to the remote system if you are connected to it through the adapter with the released or renewed lease.
Releasing and Renewing DHCP Leases on All Adapters
You can perform global DHCP address releases or renewals on all adapters by using the Win32_NetworkAdapterConfiguration methods, ReleaseDHCPLeaseAll and RenewDHCPLeaseAll. However, the command must apply to the WMI class, rather than a particular adapter, because releasing and renewing leases globally is performed on the class, not on a specific adapter. 
You can get a reference to a WMI class, instead of class instances, by listing all WMI classes and then selecting only the desired class by name. For example, the following command returns the Win32_NetworkAdapterConfiguration class:
Get-WmiObject -List | Where-Object -FilterScript {$_.Name -eq "Win32_NetworkAdapterConfiguration"}
You can treat the entire command as the class and then invoke the ReleaseDHCPAdapterLease method on it. In the following command, the parentheses surrounding the Get-WmiObject and Where-Object pipeline elements direct Windows PowerShell to evaluate them first:
( Get-WmiObject -List | Where-Object -FilterScript {$_.Name -eq "Win32_NetworkAdapterConfiguration"} ).ReleaseDHCPLeaseAll()
You can use the same command format to invoke the RenewDHCPLeaseAll method:
( Get-WmiObject -List | Where-Object -FilterScript {$_.Name -eq "Win32_NetworkAdapterConfiguration"} ).RenewDHCPLeaseAll()
Creating a Network Share
To create a network share, use the Win32_Share Create method:
(Get-WmiObject -List -ComputerName . | Where-Object -FilterScript {$_.Name -eq "Win32_Share"}).Create("C:\temp","TempShare",0,25,"test share of the temp folder")
You can also create the share by using net share in Windows PowerShell
net share tempshare=c:\temp /users:25 /remark:"test share of the temp folder"
Removing a Network Share
You can remove a network share with Win32_Share, but the process is slightly different from creating a share, because you need to retrieve the specific share to be removed, rather than the Win32_Share class.  The following statement deletes the share "TempShare":
 (Get-WmiObject -Class Win32_Share -ComputerName . -Filter "Name='TempShare'").Delete()
Net share works as well:
PS> net share tempshare /delete
tempshare was deleted successfully.
Connecting a Windows Accessible Network Drive
The New-PSDrive cmdlets creates a Windows PowerShell drive, but drives created this way are available only to Windows PowerShell. To create a new networked drive, you can use the WScript.Network COM object. The following command maps the share \\FPS01\users to local drive B:
(New-Object -ComObject WScript.Network).MapNetworkDrive("B:", "\\FPS01\users")
The net use command works as well:
net use B: \\FPS01\users
Drives mapped with either WScript.Network or net use are immediately available to Windows PowerShell.
Working with Files and Folders
Navigating through Windows PowerShell drives and manipulating the items on them is similar to manipulating files and folders on Windows physical disk drives. We will discuss how to deal with specific file and folder manipulation tasks in this section.
Listing All the Files and Folders Within a Folder
You can get all items directly within a folder by using Get-ChildItem. Add the optional Force parameter to display hidden or system items. For example, this command displays the direct contents of Windows PowerShell Drive C (which is the same as the Windows physical drive C):
Get-ChildItem -Force C:\
The command lists only the directly contained items, much like using Cmd.exe's DIR command or ls in a UNIX shell. In order to show contained items, you need to specify the - Recurse parameter as well. (This can take an extremely long time to complete.) To list everything on the C drive:
Get-ChildItem -Force C:\ -Recurse
Get-ChildItem can filter items with its Path, Filter, Include, and Exclude parameters, but those are typically based only on name. You can perform complex filtering based on other properties of items by using Where-Object. 
The following command finds all executables within the Program Files folder that were last modified after October 1, 2005 and which are neither smaller than 1 megabyte nor larger than 10 megabytes:
Get-ChildItem -Path $env:ProgramFiles -Recurse -Include *.exe | Where-Object -FilterScript {($_.LastWriteTime -gt "2005-10-01") -and ($_.Length -ge 1m) -and ($_.Length -le 10m)}
Copying Files and Folders
Copying is done with Copy-Item. The following command backs up C:\boot.ini to C:\boot.bak:
Copy-Item -Path c:\boot.ini -Destination c:\boot.bak
If the destination file already exists, the copy attempt fails. To overwrite a pre-existing destination, use the Force parameter:
Copy-Item -Path c:\boot.ini -Destination c:\boot.bak -Force
This command works even when the destination is read-only.
Folder copying works the same way. This command copies the folder C:\temp\test1 to the new folder c:\temp\DeleteMe recursively:
Copy-Item C:\temp\test1 -Recurse c:\temp\DeleteMe
You can also copy a selection of items. The following command copies all .txt files contained anywhere in c:\data to c:\temp\text:
Copy-Item -Filter *.txt -Path c:\data -Recurse -Destination c:\temp\text
You can still use other tools to perform file system copies. XCOPY, ROBOCOPY, and COM objects, such as the Scripting.FileSystemObject, all work in Windows PowerShell. For example, you can use the Windows Script Host Scripting.FileSystem COM class to back up C:\boot.ini to C:\boot.bak:
(New-Object -ComObject Scripting.FileSystemObject).CopyFile("c:\boot.ini", "c:\boot.bak")
Creating Files and Folders
Creating new items works the same on all Windows PowerShell providers. If a Windows PowerShell provider has more than one type of item—for example, the FileSystem Windows PowerShell provider distinguishes between directories and files—you need to specify the item type.
This command creates a new folder C:\temp\New Folder:
New-Item -Path 'C:\temp\New Folder' -ItemType "directory"
This command creates a new empty file C:\temp\New Folder\file.txt
New-Item -Path 'C:\temp\New Folder\file.txt' -ItemType "file"
Removing All Files and Folders Within a Folder
You can remove contained items using Remove-Item, but you will be prompted to confirm the removal if the item contains anything else. For example, if you attempt to delete the folder C:\temp\DeleteMe that contains other items, Windows PowerShell prompts you for confirmation before deleting the folder:
Remove-Item C:\temp\DeleteMe

Confirm
The item at C:\temp\DeleteMe has children and the -recurse parameter was not
specified. If you continue, all children will be removed with the item. Are you
sure you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):
If you do not want to be prompted for each contained item, specify the Recurse parameter:
Remove-Item C:\temp\DeleteMe -Recurse
Mapping a Local Folder as a Windows Accessible Drive
You can also map a local folder, using the subst command. The following command creates a local drive P: rooted in the local Program Files directory:
subst p: $env:programfiles
Just as with network drives, drives mapped within Windows PowerShell using subst are immediately visible to the Windows PowerShell session.
Reading a Text File into an Array
One of the more common storage formats for text data is in a file with separate lines treated as distinct data elements. The Get-Content cmdlet can be used to read an entire file in one step, as shown here:
PS> Get-Content -Path C:\boot.ini
[boot loader]
timeout=5
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional"
 /noexecute=AlwaysOff /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=" Microsoft Windows XP Professional 
with Data Execution Prevention" /noexecute=optin /fastdetect
Get-Content already treats the data read from the file as an array, with one element per line of file content. You can confirm this by checking the Length of the returned content: 
PS> (Get-Content -Path C:\boot.ini).Length
6
This command is most useful for getting lists of information into Windows PowerShell directly. For example, you might store a list of computer names or IP addresses in a file C:\temp\domainMembers.txt, with one name on each line of the file. You can use Get-Content to retrieve the file contents and put them in the variable $Computers:
$Computers = Get-Content -Path C:\temp\DomainMembers.txt
$Computers is now an array containing a computer name in each element.
Working with Registry Keys
Because registry keys are items on Windows PowerShell drives, working with them is very similar to working with files and folders. One critical difference is that every item on a registry-based Windows PowerShell drive is a container, just like a folder on a file system drive. However, registry entries and their associated values are properties of the items, not distinct items. 
Listing All Subkeys of a Registry Key
You can show all items directly within a registry key by using Get-ChildItem. Add the optional Force parameter to display hidden or system items. For example, this command displays the items directly within Windows PowerShell drive HKCU:, which corresponds to the HKEY_CURRENT_USER registry hive:
PS> Get-ChildItem -Path hkcu:\

   Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER

SKC  VC Name                           Property
---  -- ----                           --------
  2   0 AppEvents                      {}
  7  33 Console                        {ColorTable00, ColorTable01, ColorTab...
 25   1 Control Panel                  {Opened}
  0   5 Environment                    {APR_ICONV_PATH, INCLUDE, LIB, TEMP...}
  1   7 Identities                     {Last Username, Last User ...
  4   0 Keyboard Layout                {}
...
These are the top-level keys visible under HKEY_CURRENT_USER in the Registry Editor (Regedit.exe).
You can also specify this registry path by specifying the registry provider's name, followed by "::". The registry provider's full name is Microsoft.PowerShell.Core\Registry, but this can be shortened to just Registry. Any of the following commands will list the contents directly under HKCU:
Get-ChildItem -Path Registry::HKEY_CURRENT_USER
Get-ChildItem -Path Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER
Get-ChildItem -Path Registry::HKCU
Get-ChildItem -Path Microsoft.PowerShell.Core\Registry::HKCU
Get-ChildItem HKCU:
These commands list only the directly contained items, much like using Cmd.exe's DIR command or ls in a UNIX shell. To show contained items, you need to specify the Recurse parameter. To list all registry keys in HKCU, use the following command (This operation can take an extremely long time.):
Get-ChildItem -Path hkcu:\ -Recurse
Get-ChildItem can perform complex filtering capabilities through its Path, Filter, Include, and Exclude parameters, but those parameters are typically based only on name. You can perform complex filtering based on other properties of items by using the Where-Objectcmdlet. The following command finds all keys within HKCU:\Software that have no more than one subkey and also have exactly four values:
Get-ChildItem -Path HKCU:\Software -Recurse | Where-Object -FilterScript {($_.SubKeyCount -le 1) -and ($_.ValueCount -eq 4) }
Copying Keys
Copying is done with Copy-Item. The following command copies HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion and all of its properties to HKCU:\, creating a new key named "CurrentVersion":
Copy-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion' -Destination hkcu:
If you examine this new key in the registry editor or by using Get-ChildItem, you will notice that you do not have copies of the contained subkeys in the new location. In order to copy all of the contents of a container, you need to specify the Recurse parameter. To make the preceding copy command recursive, you would use this command:
Copy-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion' -Destination hkcu: -Recurse
You can still use other tools you already have available to perform filesystem copies. Any registry editing tools—including reg.exe, regini.exe, and regedit.exe—and COM objects that support registry editing (such as WScript.Shell and WMI's StdRegProv class) can be used from within Windows PowerShell.
Creating Keys
Creating new keys in the registry is simpler than creating a new item in a file system. Because all registry keys are containers, you do not need to specify the item type; you simply supply an explicit path, such as:
New-Item -Path hkcu:\software\_DeleteMe
You can also use a provider-based path to specify a key:
New-Item -Path Registry::HKCU\_DeleteMe
Deleting Keys
Deleting items is essentially the same for all providers. The following commands will silently remove items:
Remove-Item -Path hkcu:\Software\_DeleteMe
Remove-Item -Path 'hkcu:\key with spaces in the name'
Removing All Keys Under a Specific Key
You can remove contained items using Remove-Item, but will be prompted to confirm the removal if the item contains anything else. For example, if we attempt to delete the HKCU:\CurrentVersion subkey we created, we see this:
Remove-Item -Path hkcu:\CurrentVersion

Confirm
The item at HKCU:\CurrentVersion\AdminDebug has children and the -recurse
parameter was not specified. If you continue, all children will be removed with
 the item. Are you sure you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):
To delete contained items without prompting, specify the -Recurse parameter:
Remove-Item -Path HKCU:\CurrentVersion -Recurse
If you wanted to remove all items within HKCU:\CurrentVersion but not HKCU:\CurrentVersion itself, you could instead use:
Remove-Item -Path HKCU:\CurrentVersion\* -Recurse
Working with Registry Entries
Because registry entries are properties of keys and, as such, are not directly browsable, we need to take a slightly different approach when working with them. 
Listing Registry Entries
There are many different ways to examine registry entries. The simplest way is to get the property names associated with a key. For example, to see the names of the entries in the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion, use Get-Item. Registry keys have a property with the generic name of "Property" that is a list of registry entries in the key. The following command selects the Property property and expands the items so that they are displayed in a list.:
PS> Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion | Select-Object -ExpandProperty Property
DevicePath
MediaPathUnexpanded
ProgramFilesDir
CommonFilesDir
ProductId
To view the registry entries in a more readable form, use Get-ItemProperty:
PS> Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion

PSPath              : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SO
                      FTWARE\Microsoft\Windows\CurrentVersion
PSParentPath        : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SO
                      FTWARE\Microsoft\Windows
PSChildName         : CurrentVersion
PSDrive             : HKLM
PSProvider          : Microsoft.PowerShell.Core\Registry
DevicePath          : C:\WINDOWS\inf
MediaPathUnexpanded : C:\WINDOWS\Media
ProgramFilesDir     : C:\Program Files
CommonFilesDir      : C:\Program Files\Common Files
ProductId           : 76487-338-1167776-22465
WallPaperDir        : C:\WINDOWS\Web\Wallpaper
MediaPath           : C:\WINDOWS\Media
ProgramFilesPath    : C:\Program Files
PF_AccessoriesName  : Accessories
(default)           :
The Windows PowerShell-related properties for the key are all prefixed with "PS", such as PSPath, PSParentPath, PSChildName, and PSProvider.
You can use the "." notation for referring to the current location. You can use Set-Location to change to the CurrentVersion registry container first:
Set-Location -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
Alternatively, you can use the built-in HKLM PSDrive with Set-Location:
Set-Location -Path hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion
You can then use the "." notation for the current location to list the properties without specifying a full path:
PS> Get-ItemProperty -Path .
...
DevicePath          : C:\WINDOWS\inf
MediaPathUnexpanded : C:\WINDOWS\Media
ProgramFilesDir     : C:\Program Files
...
Path expansion works the same as it does within the file system, so from this location you can get the ItemProperty listing for HKLM:\SOFTWARE\Microsoft\Windows\Help by using Get-ItemProperty -Path ..\Help.
Getting a Single Registry Entry
If you wish to retrieve a specific entry in a registry key, you can use one of several possible approaches. This example finds the value of DevicePath in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion.
Using Get-ItemProperty, use the Path parameter to specify the name of the key, and the Name parameter to specify the name of the DevicePath entry.
PS> Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion -Name DevicePath

PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\
               Microsoft\Windows\CurrentVersion
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\
               Microsoft\Windows
PSChildName  : CurrentVersion
PSDrive      : HKLM
PSProvider   : Microsoft.PowerShell.Core\Registry
DevicePath   : C:\WINDOWS\inf
This command returns the standard Windows PowerShell properties as well as the DevicePath property.
Note
·	Although Get-ItemProperty has Filter, Include, and Exclude parameters, they cannot be used to filter by property name. These parameters refer to registry keys—which are item paths—and not registry entries—which are item properties.
Another option is to use the Reg.exe command line tool. For help with reg.exe, type reg.exe /? at a command prompt. To find the DevicePath entry, use reg.exe as shown in the following command:
PS> reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion /v DevicePath

! REG.EXE VERSION 3.0

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
    DevicePath  REG_EXPAND_SZ   %SystemRoot%\inf
You can also use the WshShell COM object as well to find some registry entries, although this method does not work with large binary data or with registry entry names that include characters such as "\"). Append the property name to the item path with a \ separator:
PS> (New-Object -ComObject WScript.Shell).RegRead("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\DevicePath")
%SystemRoot%\inf
Creating New Registry Entries
To add a new entry named "PowerShellPath" to the CurrentVersion key, use New-ItemProperty with the path to the key, the entry name, and the value of the entry. For this example, we will take the value of the Windows PowerShell variable $PSHome, which stores the path to the installation directory for Windows PowerShell.
You can add the new entry to the key by using the following command, and the command also returns information about the new entry:
PS> New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -PropertyType String -Value $PSHome

PSPath         : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWAR
                 E\Microsoft\Windows\CurrentVersion
PSParentPath   : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWAR
                 E\Microsoft\Windows
PSChildName    : CurrentVersion
PSDrive        : HKLM
PSProvider     : Microsoft.PowerShell.Core\Registry
PowerShellPath : C:\Program Files\Windows PowerShell\v1.0
The PropertyType must be the name of a Microsoft.Win32.RegistryValueKind enumeration member from the following table:

PropertyType Value	Meaning	
Binary	Binary data	
DWord	A number that is a valid UInt32	
ExpandString	A string that can contain environment variables that are dynamically expanded	
MultiString	A multiline string	
String	Any string value	
QWord	8 bytes of binary data	

Note: 
You can add a registry entry to multiple locations by specifying an array of values for the Path parameter:
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion, HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -PropertyType String -Value $PSHome

You can also overwrite a pre-existing registry entry value by adding the Force parameter to any New-ItemProperty command.
Renaming Registry Entries
To rename the PowerShellPath entry to "PSHome," use Rename-ItemProperty:
Rename-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -NewName PSHome
To display the renamed value, add the PassThru parameter to the command. 
Rename-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -NewName PSHome -passthru

Deleting Registry Entries
To delete both the PSHome and PowerShellPath registry entries, use Remove-ItemProperty:
Remove-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PSHome
Remove-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath
Appendix 1 - Compatibility Aliases

Windows PowerShell has several transition aliases that allow Unix and Cmd users to use familiar command names in Windows PowerShell. The most common aliases are shown in the table below, along with the Windows PowerShell command behind the alias and the standard Windows PowerShell alias if one exists.
Note
·	You can find the PowerShell command that any alias points to from within PowerShell by using Get-Alias. For example:
·	PS> Get-Alias cls
CommandType     Name                            Definition
-----------     ----                            ----------
Alias           cls                             Clear-Host

CMD Command	Unix Command	PS Command	PS Alias	
dir	ls	Get-ChildItem	gci	
cls	clear	Clear-Host (function)	N/A	
del, erase, rmdir	rm	Remove-Item	ri	
copy	cp	Copy-Item	ci	
move	mv	Move-Item	mi	
rename	mv	Rename-Item	rni	
type	cat	Get-Content	gc	
cd	cd	Set-Location	sl	
md	mkdir	New-Item	ni	
N/A	pushd	Push-Location	N/A	
N/A	popd	Pop-Location	N/A	

Appendix 2 - Creating a Custom PowerShell Shortcut
The following procedure will step you through creating a shortcut to PowerShell that has several convenient options customized.
1.	Create a shortcut that points to powershell.exe.
2.	Right-click the shortcut and select Properties. 
3.	Click the Options tab.
4.	To enable mouse-based select and copy, under Edit Options select the QuickEdit check box. You can then select text in the PowerShell console window by dragging the left mouse button, and copy text to the clipboard by either pressing the Enter key or right-clicking the mouse.
5.	In Edit Options, select the Insert Mode check box. You can then right-click in the console window to automatically paste text from the clipboard.
6.	In Command History, in the Buffer Size spin box, type or select a number between 1 and 999. This sets the number of typed commands that will be kept in the console buffer. 
7.	In Command History, select the Discard Old Duplicates checkbox to eliminate repeated commands from the console buffer.
8.	Click the Layout tab.
9.	In the Screen Buffer group box, type a number between 1 and 9999 in the Height scroll box. The height represents the number of lines of output buffered. This is the maximum number of lines retained for viewing when you scroll through the console window. If this number is lower than the height shown in the Window size box, the Window size height will automatically be reduced to the same value. 
10.	In the Window Size group box, type a number between 1 and 9999 for width. This represents the number of characters that are displayed across the console window. The default width is 80, and PowerShell's output formatting is designed with this width in mind.  
11.	If you want to place the console at a particular point on the desktop when it is opened, in the Window position group box, clear the Let system position window check box, and then, in Window Position, change the values in Left and Top.
12.	When finished, click the OK button.