A Guided Tour of Windows PowerShell
Introduction
Windows PowerShell promises to revolutionize the world of system management and command-line shells. From its object-based pipelines to its administrator focus to its enormous reach into other Microsoft management technologies, PowerShell drastically improves the productivity of administrators and power users alike.
When you’re learning a new technology, it is natural to feel bewildered at first by all the unfamiliar features and functionality. This perhaps rings especially true for users new to Windows PowerShell because it may be their first experience with a fully featured command-line shell. Or worse, they’ve heard stories of PowerShell’s fantastic integrated scripting capabilities and fear being forced into a world of programming that they’ve actively avoided until now.
Fortunately, these fears are entirely misguided; PowerShell is a shell that both grows with you and grows on you. Let’s take a tour to see what it is capable of:
PowerShell works with standard Windows commands and applications. You don’t have to throw away what you already know and use.
PowerShell introduces a powerful new type of command. PowerShell commands (called cmdlets) share a common
Verb-Noun
syntax and offer many usability improvements over standard commands.PowerShell understands objects. Working directly with richly structured objects makes working with (and combining) PowerShell commands immensely easier than working in the plain-text world of traditional shells.
PowerShell caters to administrators. Even with all its advances, PowerShell focuses strongly on its use as an interactive shell: the experience of entering commands in a running PowerShell application.
PowerShell supports discovery. Using three simple commands, you can learn and discover almost anything PowerShell has to offer.
PowerShell enables ubiquitous scripting. With a fully fledged scripting language that works directly from the command line, PowerShell lets you automate tasks with ease.
PowerShell bridges many technologies. By letting you work with .NET, COM, WMI, XML, and Active Directory, PowerShell makes working with these previously isolated technologies easier than ever before.
PowerShell simplifies management of datastores. Through its provider model, PowerShell lets you manage datastores using the same techniques you already use to manage files and folders.
We’ll explore each of these pillars in this introductory tour of PowerShell. If you are running Windows 7 (or later) or Windows 2008 R2 (or later), PowerShell is already installed. If not, visit the download link to install it. PowerShell and its supporting technologies are together referred to as the Windows Management Framework.
An Interactive Shell
At its core, PowerShell is first and foremost an interactive shell. While it supports scripting and other powerful features, its focus as a shell underpins everything.
Getting started in PowerShell is a simple matter of launching PowerShell.exe rather than cmd.exe—the shells begin to diverge as you explore the intermediate and advanced functionality, but you can be productive in PowerShell immediately.
To launch Windows PowerShell, do one of the following:
Click Start→All Programs→Accessories→Windows PowerShell
Click Start→Run, and then type
PowerShell
A PowerShell prompt window opens that’s nearly identical to the traditional
command prompt window of Windows XP, Windows Server 2003, and their many ancestors. The
PS C:\Users\Lee>
prompt indicates that PowerShell is
ready for input, as shown in Figure 1.
Once you’ve launched your PowerShell prompt, you can enter
DOS-style and Unix-style commands to navigate around the filesystem just
as you would with any Windows or Unix command prompt—as in the interactive
session shown in Example 1. In this example, we
use the pushd
, cd
, dir
,
pwd
, and popd
commands to store the current location,
navigate around the filesystem, list items in the current directory, and
then return to the original location. Try it!
PS C:\Documents and Settings\Lee> function Prompt { "PS > " } PS > pushd . PS > cd \ PS > dir Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 11/2/2006 4:36 AM $WINDOWS.~BT d---- 5/8/2007 8:37 PM Blurpark d---- 11/29/2006 2:47 PM Boot d---- 11/28/2006 2:10 PM DECCHECK d---- 10/7/2006 4:30 PM Documents and Settings d---- 5/21/2007 6:02 PM F&SC-demo d---- 4/2/2007 7:21 PM Inetpub d---- 5/20/2007 4:59 PM Program Files d---- 5/21/2007 7:26 PM temp d---- 5/21/2007 8:55 PM Windows -a--- 1/7/2006 10:37 PM 0 autoexec.bat -ar-s 11/29/2006 1:39 PM 8192 BOOTSECT.BAK -a--- 1/7/2006 10:37 PM 0 config.sys -a--- 5/1/2007 8:43 PM 33057 RUU.log -a--- 4/2/2007 7:46 PM 2487 secedit.INTEG.RAW PS > popd PS > pwd Path ---- C:\Documents and Settings\Lee
In this example, our first command customizes the prompt. In
cmd.exe, customizing the prompt looks like prompt $P$G
. In bash, it looks like PS1="[\h] \w> "
. In PowerShell, you define a function that returns whatever
you want displayed.
The
pushd
command is an alternative name (alias) to the much
more descriptively named PowerShell command Push-Location
. Likewise, the cd
, dir
, popd
, and pwd
commands all have
more memorable counterparts.
Although navigating around the filesystem is helpful, so is running the tools you know and
love, such as ipconfig
and notepad
. Type the command name and you’ll see
results like those shown in Example 2.
PS > ipconfig Windows IP Configuration Ethernet adapter Wireless Network Connection 4: Connection-specific DNS Suffix . : hsd1.wa.comcast.net. IP Address. . . . . . . . . . . . : 192.168.1.100 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : 192.168.1.1 PS > notepad (notepad launches)
Entering ipconfig
displays the IP addresses of your
current network connections. Entering notepad
runs—as you’d
expect—the Notepad editor that ships with Windows. Try them both on your
own machine.
Structured Commands (Cmdlets)
In addition to supporting traditional Windows executables, PowerShell introduces a
powerful new type of command called a cmdlet (pronounced “command-let”). All cmdlets are named in a Verb-Noun
pattern, such as Get-Process
, Get-Content
, and Stop-Process
.
PS > Get-Process -Name lsass Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 668 13 6228 1660 46 932 lsass
In this example, you provide a value to the
ProcessName
parameter to get a specific
process by name.
Note
Once you know the handful of common verbs in
PowerShell, learning how to work with new nouns becomes much easier.
While you may never have worked with a certain object before (such as a
Service), the standard Get
, Set
, Start
,
and Stop
actions still apply. For a
list of these common verbs, see Table 10-1 in Chapter 10.
You don’t always have to type these full cmdlet names, however. PowerShell lets you
use the Tab
key to autocomplete cmdlet names and parameter
names:
PS > Get-Pr<TAB
> -N<TAB
> lsass
For quick interactive use, even that may be too much typing. To help improve your
efficiency, PowerShell defines aliases for all common commands and lets you define your own.
In addition to alias names, PowerShell requires only that you type enough of the parameter
name to disambiguate it from the rest of the parameters in that cmdlet. PowerShell is also
case-insensitive. Using the built-in gps
alias (which
represents the Get-Process
cmdlet) along with parameter
shortening, you can instead type:
PS > gps -n lsass
Going even further, PowerShell supports
positional parameters on cmdlets.
Positional parameters let you provide parameter values in a certain
position on the command line, rather than having to specify them by name.
The Get-Process
cmdlet takes a process
name as its first positional parameter. This parameter even supports wildcards:
PS > gps l*s
Deep Integration of Objects
PowerShell begins to flex more of its muscle as you explore the way it handles structured data and richly functional objects. For example, the following command generates a simple text string. Since nothing captures that output, PowerShell displays it to you:
PS > "Hello World" Hello World
The string you just generated is, in fact, a fully functional
object from the .NET Framework. For example, you can access its Length
property, which
tells you how many characters are in the string. To access a property, you
place a dot between the object and its property name:
PS > "Hello World".Length 11
All PowerShell commands that produce output
generate that output as objects as well. For example, the Get-Process
cmdlet
generates a System.Diagnostics.Process
object, which you can store in a variable. In PowerShell, variable names
start with a $
character. If you have
an instance of Notepad running, the following command stores a reference
to it:
$process = Get-Process notepad
Since this is a fully functional Process
object from the .NET Framework, you can
call methods on that object to perform actions on it. This command calls
the Kill()
method, which
stops a process. To access a method, you place a dot between the object and its
method name:
$process.Kill()
PowerShell supports this functionality more
directly through the Stop-Process
cmdlet, but
this example demonstrates an important point about your ability to
interact with these rich objects.
Administrators as First-Class Users
While PowerShell’s support for objects from the .NET Framework
quickens the pulse of most users, PowerShell continues to focus strongly
on administrative tasks. For example, PowerShell supports MB
(for megabyte) and GB
(for gigabyte) as some of its standard
administrative constants. For example, how many disks will it take to back
up a 40 GB hard drive to CD-ROM?
PS > 40GB / 650MB 63.0153846153846
Although the .NET Framework is traditionally a development platform, it contains a wealth of functionality useful for administrators too! In fact, it makes PowerShell a great calendar. For example, is 2008 a leap year? PowerShell can tell you:
PS > [DateTime]::IsLeapYear(2008) True
Going further, how might you determine how much
time remains until summer? The following command converts "06/21/2011"
(the start of summer) to a date,
and then subtracts the current date from that. It stores the result in the
$result
variable, and then accesses the
TotalDays
property.
PS > $result = [DateTime] "06/21/2011" - [DateTime]::Now PS > $result.TotalDays 283.0549285662616
Composable Commands
Whenever a command generates output, you can use a pipeline character (|) to pass that output directly to another command as input. If the second command understands the objects produced by the first command, it can operate on the results. You can chain together many commands this way, creating powerful compositions out of a few simple operations. For example, the following command gets all items in the Path1 directory and moves them to the Path2 directory:
Get-Item Path1\* | Move-Item -Destination Path2
You can create even more complex commands by
adding additional cmdlets to the pipeline. In Example 3, the first command
gets all processes running on the system. It passes those to the Where-Object
cmdlet, which runs a comparison
against each incoming item. In this case, the comparison is $_.Handles -ge 500
, which checks whether the
Handles
property of the current
object (represented by the $_
variable) is greater than or equal to
500
. For each object in which this
comparison holds true, you pass the results to the Sort-Object
cmdlet, asking it to sort items by
their Handles
property. Finally, you
pass the objects to the Format-Table
cmdlet to generate a table that contains the Handles
, Name
, and Description
of the process.
PS > Get-Process | Where-Object { $_.Handles -ge 500 } | Sort-Object Handles | Format-Table Handles,Name,Description -Auto Handles Name Description ------- ---- ----------- 588 winlogon 592 svchost 667 lsass 725 csrss 742 System 964 WINWORD Microsoft Office Word 1112 OUTLOOK Microsoft Office Outlook 2063 svchost
Techniques to Protect You from Yourself
While aliases, wildcards, and composable pipelines are powerful, their use in commands that modify system information can easily be nerve-racking. After all, what does this command do? Think about it, but don’t try it just yet:
PS > gps [b-t]*[c-r] | Stop-Process
It appears to stop all processes that begin
with the letters b
through t
and end with the letters c
through r
.
How can you be sure? Let PowerShell tell you. For commands that modify
data, PowerShell supports -WhatIf
and -Confirm
parameters that
let you see what a command would do:
PS > gps [b-t]*[c-r] | Stop-Process -whatif What if: Performing operation "Stop-Process" on Target "ctfmon (812)". What if: Performing operation "Stop-Process" on Target "Ditto (1916)". What if: Performing operation "Stop-Process" on Target "dsamain (316)". What if: Performing operation "Stop-Process" on Target "ehrecvr (1832)". What if: Performing operation "Stop-Process" on Target "ehSched (1852)". What if: Performing operation "Stop-Process" on Target "EXCEL (2092)". What if: Performing operation "Stop-Process" on Target "explorer (1900)". (...)
In this interaction, using the -WhatIf
parameter with the Stop-Process
pipelined command lets you preview
which processes on your system will be stopped before you actually carry
out the operation.
Note that this example is not a dare! In the words of one reviewer:
Common Discovery Commands
While reading through a guided tour is helpful, I find that most
learning happens in an ad hoc fashion. To find all commands that match a
given wildcard, use the Get-Command
cmdlet. For example, by
entering the following, you can find out which PowerShell commands (and
Windows applications) contain the word
process.
PS > Get-Command *process* CommandType Name Definition ----------- ---- ---------- Cmdlet Get-Process Get-Process [[-Name] <Str... Application qprocess.exe c:\windows\system32\qproc... Cmdlet Stop-Process Stop-Process [-Id] <Int32...
To see what a command such as Get-Process
does, use the Get-Help
cmdlet, like this:
PS > Get-Help Get-Process
Since PowerShell lets you work with objects from the .NET
Framework, it provides the Get-Member
cmdlet to retrieve information about the properties and methods that an
object, such as a .NET System.String
,
supports. Piping a string to the Get-Member
command displays its type name and
its members:
PS > "Hello World" | Get-Member TypeName: System.String Name MemberType Definition ---- ---------- ---------- (...) PadLeft Method System.String PadLeft(Int32 tota... PadRight Method System.String PadRight(Int32 tot... Remove Method System.String Remove(Int32 start... Replace Method System.String Replace(Char oldCh... Split Method System.String[] Split(Params Cha... StartsWith Method System.Boolean StartsWith(String... Substring Method System.String Substring(Int32 st... ToCharArray Method System.Char[] ToCharArray(), Sys... ToLower Method System.String ToLower(), System.... ToLower- Invariant Method System.String ToLowerInvariant() ToString Method System.String ToString(), System... ToUpper Method System.String ToUpper(), System.... ToUpper- Invariant Method System.String ToUpperInvariant() Trim Method System.String Trim(Params Char[]... TrimEnd Method System.String TrimEnd(Params Cha... TrimStart Method System.String TrimStart(Params C... Chars Parameter- System.Char Chars(Int32 index) {... izedProperty Length Property System.Int32 Length {get;}
Ubiquitous Scripting
PowerShell makes no distinction between the commands typed at the command line and the commands written in a script. Your favorite
cmdlets work in scripts and your favorite scripting techniques (e.g., the foreach
statement) work directly on the command line. For example,
to add up the handle count for all running processes:
PS > $handleCount = 0 PS > foreach($process in Get-Process) { $handleCount += $process.Handles } PS > $handleCount 19403
While PowerShell provides a command (Measure-Object
) to measure statistics about
collections, this short example shows how PowerShell lets you apply
techniques that normally require a separate scripting or programming
language.
In addition to using PowerShell scripting keywords, you can also create and work directly with objects from the .NET Framework that you may be familiar with. PowerShell becomes almost like the C# immediate mode in Visual Studio. Example 4 shows how PowerShell lets you easily interact with the .NET Framework.
PS > $webClient = New-Object System.Net.WebClient PS > $content = $webClient.DownloadString("http://blogs.msdn. com/PowerShell/rss.aspx") PS > $content.Substring(0,1000) <?xml version="1.0" encoding="UTF-8" ?> <?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/ utility/FeedS tylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns: dc="http://pu rl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/ modules/slas h/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel> <title>Windo (...)
Ad Hoc Development
By blurring the lines between interactive administration and
writing scripts, the history buffers of PowerShell sessions quickly become
the basis for ad hoc script development. In this example, you call the
Get-History
cmdlet to
retrieve the history of your session. For each item, you get its CommandLine
property (the thing you typed) and
send the output to a new script file.
PS > Get-History | Foreach-Object { $_.CommandLine } > c: \temp\script.ps1 PS > notepad c:\temp\script.ps1 (save the content you want to keep) PS > c:\temp\script.ps1
Note
If this is the first time you’ve run a script in PowerShell, you
will need to configure your execution policy. For more information about selecting an
execution policy, type help about_signing
.
.
Bridging Technologies
We’ve seen how PowerShell lets you fully leverage the .NET Framework in your tasks, but its support for common technologies stretches even further. As Example 5 (continued from Example 4) shows, PowerShell supports XML.
PS > $xmlContent = [xml] $content PS > $xmlContent xml xml-stylesheet rss --- -------------- --- version="1.0" encoding... type="text/xsl" href="... rss PS > $xmlContent.rss version : 2.0 dc : http://purl.org/dc/elements/1.1/ slash : http://purl.org/rss/1.0/modules/slash/ wfw : http://wellformedweb.org/CommentAPI/ channel : channel PS > $xmlContent.rss.channel.item | select Title title ----- CMD.exe compatibility Time Stamping Log Files Microsoft Compute Cluster now has a PowerShell Provider and Cmdlets The Virtuous Cycle: .NET Developers using PowerShell (...)
PowerShell also lets you work with Windows Management Instrumentation (WMI) and CIM:
PS > Get-CimInstance Win32_Bios SMBIOSBIOSVersion : ASUS A7N8X Deluxe ACPI BIOS Rev 1009 Manufacturer : Phoenix Technologies, LTD Name : Phoenix - AwardBIOS v6.00PG SerialNumber : xxxxxxxxxxx Version : Nvidia - 42302e31
Or, as Example 6 shows, you can work with Active Directory Service Interfaces (ADSI).
PS > [ADSI] "WinNT://./Administrator" | Format-List * UserFlags : {66113} MaxStorage : {-1} PasswordAge : {19550795} PasswordExpired : {0} LoginHours : {255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255} FullName : {} Description : {Built-in account for administering the computer/ domain} BadPasswordAttempts : {0} LastLogin : {5/21/2007 3:00:00 AM} HomeDirectory : {} LoginScript : {} Profile : {} HomeDirDrive : {} Parameters : {} PrimaryGroupID : {513} Name : {Administrator} MinPasswordLength : {0} MaxPasswordAge : {3710851} MinPasswordAge : {0} PasswordHistoryLength : {0} AutoUnlockInterval : {1800} LockoutObservationInterval : {1800} MaxBadPasswordsAllowed : {0} RasPermissions : {1} objectSid : {1 5 0 0 0 0 0 5 21 0 0 0 121 227 252 83 122 130 50 34 67 23 10 50 244 1 0 0}
Or, as Example 7 shows, you can even use PowerShell for scripting traditional COM objects.
PS > $firewall = New-Object -com HNetCfg.FwMgr PS > $firewall.LocalPolicy.CurrentProfile Type : 1 FirewallEnabled : True ExceptionsNotAllowed : False NotificationsDisabled : False UnicastResponsesToMulti- castBroadcastDisabled : False RemoteAdminSettings : System.__ComObject IcmpSettings : System.__ComObject GloballyOpenPorts : {Media Center Extender Serv ice, Remote Media Center Ex perience, Adam Test Instanc e, QWAVE...} Services : {File and Printer Sharing, UPnP Framework, Remote Desk top} AuthorizedApplications : {Remote Assistance, Windows Messenger, Media Center, Trillian...}
Namespace Navigation Through Providers
Another avenue PowerShell offers for working with the system is providers. PowerShell providers let you navigate and manage data stores using the same techniques you already use to work with the filesystem, as illustrated in Example 8.
PS > Set-Location c:\ PS > Get-ChildItem Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 11/2/2006 4:36 AM $WINDOWS.~BT d---- 5/8/2007 8:37 PM Blurpark d---- 11/29/2006 2:47 PM Boot d---- 11/28/2006 2:10 PM DECCHECK d---- 10/7/2006 4:30 PM Documents and Settings d---- 5/21/2007 6:02 PM F&SC-demo d---- 4/2/2007 7:21 PM Inetpub d---- 5/20/2007 4:59 PM Program Files d---- 5/21/2007 11:47 PM temp d---- 5/21/2007 8:55 PM Windows -a--- 1/7/2006 10:37 PM 0 autoexec.bat -ar-s 11/29/2006 1:39 PM 8192 BOOTSECT.BAK -a--- 1/7/2006 10:37 PM 0 config.sys -a--- 5/1/2007 8:43 PM 33057 RUU.log -a--- 4/2/2007 7:46 PM 2487 secedit.INTEG.RAW
This also works on the registry, as shown in Example 9.
PS > Set-Location HKCU:\Software\Microsoft\Windows\ PS > Get-ChildItem Hive: HKEY_CURRENT_USER\Software\Microsoft\Windows SKC VC Name Property --- -- ---- -------- 30 1 CurrentVersion {ISC} 3 1 Shell {BagMRU Size} 4 2 ShellNoRoam {(default), BagMRU Size} PS > Set-Location CurrentVersion\Run PS > Get-ItemProperty . (...) FolderShare : "C:\Program Files\FolderShare\ FolderShare.exe" /background TaskSwitchXP : d:\lee\tools\TaskSwitchXP.exe ctfmon.exe : C:\WINDOWS\system32\ctfmon.exe Ditto : C:\Program Files\Ditto\Ditto.exe (...)
And it even works on the machine’s certificate store, as Example 10 illustrates.
PS > Set-Location cert:\CurrentUser\Root PS > Get-ChildItem Directory: Microsoft.PowerShell.Security\ Certificate::CurrentUser\Root Thumbprint Subject ---------- ------- CDD4EEAE6000AC7F40C3802C171E30148030C072 CN=Microsoft Root Certificate... BE36A4562FB2EE05DBB3D32323ADF445084ED656 CN=Thawte Timestamping CA, OU... A43489159A520F0D93D032CCAF37E7FE20A8B419 CN=Microsoft Root Authority, ... 9FE47B4D05D46E8066BAB1D1BFC9E48F1DBE6B26 CN=PowerShell Local Certifica... 7F88CD7223F3C813818C994614A89C99FA3B5247 CN=Microsoft Authenticode(tm)... 245C97DF7514E7CF2DF8BE72AE957B9E04741E85 OU=Copyright (c) 1997 Microso... (...)
Much, Much More
As exciting as this guided tour was, it barely scratches the surface of how you can use PowerShell to improve your productivity and systems management skills. For more information about getting started in PowerShell, see the “Getting Started” and “User Guide” files included in the Windows PowerShell section of your Start menu. For a cookbook-style guide to PowerShell (and hard-won solutions to its most common problems), you may be interested in the source of the material in this pocket reference: my book Windows PowerShell Cookbook, 3rd Edition (O’Reilly).
Get Windows PowerShell Pocket Reference, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.