A Guided Tour of PowerShell

Introduction

PowerShell has revolutionized 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’s natural to feel bewildered at first by all the unfamiliar features and functionality. This perhaps rings especially true for users new to 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 data stores. Through its provider model, PowerShell lets you manage data stores 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’re running any supported version of Windows (Windows 7 or later, or Windows 2012 R2 or later), Windows PowerShell is already installed. That said, a significant step up from this default installation is the open source PowerShell Core.

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 PowerShell, click Start and then type PowerShell (or pwsh if you’ve jumped ahead!).

A PowerShell prompt window opens that’s nearly identical to the traditional command prompt of its ancestors. The PS C:\Users\Lee> prompt indicates that PowerShell is ready for input, as shown in Figure P-1.

wpsp 0001
Figure P-1. Windows PowerShell, ready for input

Once you’ve launched your PowerShell prompt, you can enter DOS- 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 P-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!

Example P-1. Entering many standard DOS- and Unix-style file manipulation commands produces the same results you get when you use them with any other Windows shell
PS C:\Users\Lee> function prompt { "PS > " }
PS > pushd .
PS > cd \
PS > dir

    Directory: C:\

Mode             LastWriteTime      Length Name
----             -------------      ------ ----
d----       5/8/2007   8:37 PM             Blurpark
d----       5/15/2016  4:32 PM             Chocolatey
d----        3/8/2020 12:45 PM             DXLab
d----       4/30/2020  7:00 AM             Go
d----        4/2/2016  3:05 PM             Intel
d-r--      12/15/2020  1:41 PM             Program Files
d-r--      11/28/2020  5:06 PM             Program Files (x86)
d----       5/12/2019  6:37 PM             Python27
d----       3/25/2018  1:11 PM             Strawberry
d----      12/16/2020  8:13 AM             temp
d-r--       8/11/2020  5:02 PM             Users
da---      12/16/2020 10:51 AM             Windows

PS > popd
PS > pwd

Path
----
C:\Users\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 P-2.

Example P-2. Windows tools and applications such as ipconfig run in PowerShell just as they do in cmd.exe
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. Similarly, 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-Pro<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. How many GIF memes will fit in a 800 GB hard drive?

PS > 800GB / 2.2MB
372363.636363636

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 2096 a leap year? PowerShell can tell you:

PS > [DateTime]::IsLeapYear(2096)
True

Going further, how might you determine how much time remains until the Y2038 Epochalypse? The following command converts "01/19/2038" (the date of the Year 2038 problem) 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] "01/19/2038" - [DateTime]::Now
PS > $result.TotalDays
6242.49822756465

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 P-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.

Example P-3. You can build more complex PowerShell commands by using pipelines to link cmdlets, as shown here with Get-Process, Where-Object, Sort-Object, and Format-Table
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 "ctfmon (812)".
What if: Performing operation "Stop-Process" on "Ditto (1916)".
What if: Performing operation "Stop-Process" on "dsamain (316)".
What if: Performing operation "Stop-Process" on "ehrecvr (1832)".
What if: Performing operation "Stop-Process" on "ehSched (1852)".
What if: Performing operation "Stop-Process" on "EXCEL (2092)".
What if: Performing operation "Stop-Process" on "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:

Not only did it stop everything, but on one of my old machines, it forced a shutdown with only one minute warning!

It was very funny though…At least I had enough time to save everything first!

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....
ToLowerInvariant Method       System.String ToLowerInvariant()
ToString         Method       System.String ToString(), System...
ToUpper          Method       System.String ToUpper(), System....
ToUpperInvariant 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...
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 P-4 shows how PowerShell lets you easily interact with the .NET Framework.

Example P-4. Using objects from the .NET Framework to retrieve a web page and process its content
PS > $webClient = New-Object System.Net.WebClient
PS > $content = $webClient.DownloadString(
                "https://devblogs.microsoft.com/powershell/feed/")
PS > $content.Substring(0,1000)
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
        xmlns:content="http://purl.org/rss/1.0/modules/content/"
        xmlns:wfw="http://wellformedweb.org/CommentAPI/"
        xmlns:dc="http://purl.org/dc/elements/1.1/"
        xmlns:atom="http://www.w3.org/2005/Atom"
        xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
        xmlns:slash="http://purl.org/rss/1.0/modules/slash/" >
<channel>
        <title>PowerShell</title>
        <atom:link href="https://devblogs.microsoft.com/powersh..."
        <link>https://devblogs.microsoft.com/powershell</link>
        <description>Automating the world one-liner at a time…
        </description>
(...)

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’ll need to configure your execution policy.

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 farther. As Example P-5 (continued from Example P-4) shows, PowerShell supports XML.

Example P-5. Working with XML content in PowerShell
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
content : http://purl.org/rss/1.0/modules/content/
wfw     : http://wellformedweb.org/CommentAPI/
dc      : http://purl.org/dc/elements/1.1/
atom    : http://www.w3.org/2005/Atom
sy      : http://purl.org/rss/1.0/modules/syndication/
slash   : http://purl.org/rss/1.0/modules/slash/
channel : channel

PS > $xmlContent.rss.channel.item | select Title

title
-----
PowerShell 7.2 Preview 2 release
Announcing PowerShell Crescendo Preview.1
You’ve got Help!
SecretManagement preview 6 and SecretStore preview 4
Announcing PowerShell 7.1
Announcing PSReadLine 2.1+ with Predictive IntelliSense
Updating help for the PSReadLine module
PowerShell Working Groups
(...)

PowerShell also lets you work with Windows Management Instrumentation (WMI) and Common Information Model (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 P-6 shows, you can work with Active Directory Service Interfaces (ADSI).

Example P-6. Working with Active Directory in PowerShell
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 P-7 shows, you can even use PowerShell for scripting traditional COM objects.

Example P-7. Working with COM objects in PowerShell
PS > $firewall = New-Object -com HNetCfg.FwMgr
PS > $firewall.LocalPolicy.CurrentProfile

Type                                         : 1
FirewallEnabled                              : True
ExceptionsNotAllowed                         : False
NotificationsDisabled                        : False
UnicastResponsesToMulticastBroadcastDisabled : False
RemoteAdminSettings                          : System.__ComObject
IcmpSettings                                 : System.__ComObject
GloballyOpenPorts                            : {Media Center
                                               Extender Service,
                                               Remote Media Center
                                               Experience, Adam
                                               Test Instance,
                                               QWAVE...}
Services                                     : {File and Printer
                                               Sharing, UPnP
                                               Framework, Remote
                                               Desktop}
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 P-8.

This also works on the registry, as shown in Example P-9.

And it even works on the machine’s certificate store, as Example P-10 illustrates.

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.

Conventions Used in This Book

The following typographical conventions are used in this book:

Italic

Indicates new terms, URLs, email addresses, filenames, and file extensions.

Constant width

Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.

Constant width bold

Shows commands or other text that should be typed literally by the user.

Constant width italic

Shows text that should be replaced with user-supplied values or by values determined by context.

Using Code Examples

Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/LeeHolmes/PowerShellCookbook.

If you have a technical question or a problem using the code examples, please send an email to .

This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission.

We appreciate, but generally do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “PowerShell Pocket Reference by Lee Holmes (O’Reilly), 3rd edition. Copyright 2021 Lee Holmes, 978-1-098-10167-1.”

If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at .

O’Reilly Online Learning

Note

For more than 40 years, O’Reilly Media has provided technology and business training, knowledge, and insight to help companies succeed.

Our unique network of experts and innovators share their knowledge and expertise through books, articles, and our online learning platform. O’Reilly’s online learning platform gives you on-demand access to live training courses, in-depth learning paths, interactive coding environments, and a vast collection of text and video from O’Reilly and 200+ other publishers. For more information, visit http://oreilly.com.

How to Contact Us

Please address comments and questions concerning this book to the publisher:

  • O’Reilly Media, Inc.
  • 1005 Gravenstein Highway North
  • Sebastopol, CA 95472
  • 800-998-9938 (in the United States or Canada)
  • 707-829-0515 (international or local)
  • 707-829-0104 (fax)

We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at https://oreil.ly/powershell-pocket-3rd.

Email to comment or ask technical questions about this book.

For news and information about our books and courses, visit http://oreilly.com.

Find us on Facebook: http://facebook.com/oreilly

Follow us on Twitter: http://twitter.com/oreillymedia

Watch us on YouTube: http://youtube.com/oreillymedia

Get PowerShell Pocket Reference, 3rd 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.