Powershell 4n00bs
Powershell 4n00bs
4N00bs
Don Jones
This book is for sale at
http://leanpub.com/powershell-4n00bs
2. A Note on Code . . . . . . . . . . . . . . . . . . . . . 3
3. What is PowerShell? . . . . . . . . . . . . . . . . . . 4
What Came Before . . . . . . . . . . . . . . . . . . . . 6
Introducing PowerShell . . . . . . . . . . . . . . . . . 10
OK - Why Should I Care? . . . . . . . . . . . . . . . . 14
4. Installing PowerShell . . . . . . . . . . . . . . . . . 17
Windows PowerShell . . . . . . . . . . . . . . . . . . 17
PowerShell Core . . . . . . . . . . . . . . . . . . . . . 18
VS Code . . . . . . . . . . . . . . . . . . . . . . . . . . 19
The Internet . . . . . . . . . . . . . . . . . . . . . . . . 31
PowerShell Gallery . . . . . . . . . . . . . . . . . . . . 32
Your Own Gallery . . . . . . . . . . . . . . . . . . . . 35
Seeing What Modules and Commands You Have . 36
What’s in a Module? . . . . . . . . . . . . . . . . . . . 37
Explore What’s Out There . . . . . . . . . . . . . . . 38
That’s meant as one long line of code. But it won’t fit in the
book, so the backslash character gets used at the end of the
overly long line, as a kind of visual “word wrap” character.
We realize that this is completely not ideal, but sometimes
there’s not much we can do about it.
As a result, you’ll sometimes see some nasty formatting like
that in this book. Other times, we may have truncated the
output a bit from what you’d normally see in PowerShell,
just to make it fit without the backslashes. We hope you’ll
understand.
3. What is PowerShell?
If you’ve used any kind of computer, even that “pocket
computer” you call a phone, then you probably have a good
idea of how computers work. You click (or tap) icons, you
type text into text fields, you drag stuff with a mouse or
your finger, and so on. Easy. In the computer world, that’s
called using a Graphical User Interface, although most of us
geeks would call it a “GUI” (pronounced, “gooey,” like melted
chocolate). GUIs are great. Almost anyone can pick up a
modern computer and start using it right off the bat, because
GUIs kind of make it easier to figure out what you need to do.
The same principle applies if you’re working with the bigger
computers that run networks, power the Internet, and un-
derpin the cloud. Called servers (because they “serve up the
goods” to your “client computer”), these expensive machines
need people to configure them, install software updates, add
new applications, and so on, and GUIs have always made
that easy. Need to install updates? Just click the “Updates”
button! Easy! Need to change a piece of configuration infor-
mation, like the network address the computer is reachable
at? No problem! Go into the Settings app, click on “Network
Settings,” and type the correct address into the text box. Easy!
Where GUIs suck is scale. Scale is a big thing in the computing
industry, and it basically means, “how large can this thing get
before it becomes a problem?” Elementary school classrooms,
for example, don’t scale well. Stick 20 kids in a class and
you’re probably fine. 25 might be pushing it. 30 starts to feel
What is PowerShell? 5
like a bit too much. By 50, it’s all fallen apart and the kids are
trying to eat each other, because they’ve already eaten the
teacher.
Scale is important in all kinds of industries. Take cars, for
example. Back in the day, before good old Henry Ford came
along. Cars were put together by hand. That didn’t scale well.
If it took 5 guys to build a car, and you wanted to build 10 cars
at once, you needed 50 guys. If you wanted 20 at once, you
needed 100 guys. Eventually, you ran outta guys. But Henry
built machines, so that a car could be built by 2 guys using
all the machines — and faster, too! And those same 2 guys
could build cars all day! Henry increased his scale through
automation.
GUIs are a bit like those 5 guys building 1 car. If it takes you
5 minutes to complete a task, then it’ll take you those same 5
minutes every time you need to perform that task. If you do
that task 70 times a day, that’s pretty much all you’re going to
be doing all day. If the business needs that task performed 150
times, you’re either going to be putting in a lot of overtime or
hiring a friend. And you’re both going to end up really bored,
doing that same task over and over and over and over and
over.
So PowerShell is the Henry Ford of computer administration.
Instead of clicking buttons and dragging things, you write
down what you want the computer to do. You write it down
in a kind of language that both you and the computer can
understand. Then, when you need the task performed, you
just basically point to those instructions, and the computer
does it. It does it faster than you, and more reliably, because
it never gets bored of doing the same thing over and over and
over and over.
What is PowerShell? 6
time you experienced it, and then you’re like, “um, no, I’ll stay
inside all summer, thanks.” But seriously, lots of folks working
on computers don’t even think these things are problems,
but I’ll try and make a case that they are, indeed, big bad
problems.
The pipe is the important part, here. It’s the idea that one
command’s output can be used by another command. String-
ing them all together lets us achieve some powerful results,
such as shutting down just the process named httpd, which is
what the above command-line does. The problem here is that
traditional commands just produce these enormous wedges
of text as output. For example, here’s a bit of what ps outputs
if you just run it by itself:
What is PowerShell? 9
Both of these are poor solutions, because they just add to the
amount of information everyone has to remember.
Introducing PowerShell
First, we should get some terminology right.
In 2006, Microsoft introduced Windows PowerShell 1.0. Through-
out the next decade, they released new versions of Windows
PowerShell: 2.0, 3.0, 4.0, 5.0, and 5.1. Good times!
But for version 6, Microsoft took a different tack. In 2017,
they released the first version of PowerShell Core, or just
“PowerShell,” with no “Windows” attached. It’s technically
version 6, but it’s the first version that runs on Windows,
Linux, and macOS. It’s a bit trimmed-down from its Windows
cousin. And, at the same time, Microsoft announced that
Windows PowerShell would basically stop at version 5.1.
Plain-old PowerShell (more properly, “PowerShell Core”) is
the go-forward product, and that’s what this book is about.
From its beginning, though, PowerShell was designed to
solve three problems, two of which are the ones I’ve already
introduced you to.
Solution 1: Consistency
PowerShell’s first step was to take all the weird command
names and ditch ‘em. Instead, PowerShell defines a naming
What is PowerShell? 11
Solution 3: Admin-Friendly
There’s another problem that isn’t specific to traditional CLIs.
See, the fact is that Windows, Linux, and other operating
systems already have all the tools you need to perform almost
any task you might need. But most of those “tools” are really
designed for software developers, and they’re built in a way
that is comfortable and familiar to software developers, but
often confusing and antagonistic to anyone else. For example,
Windows has the ability to terminate a running app. All you
have to do is run code like this:
What is PowerShell? 13
1 System.Diagonstics.Process p =
2 New System.Diagnostics.Process()
3
4 p.GetProcessById(1234)
5 // assumes you know that 1234 is the app you want
6
7 p.Kill()
Easy, right? Well, if you’re a developer, it’s very easy. All you
do is type in that code, compile the code into an executable,
and run the executable. Takes maybe 10 minutes.
PowerShell would just want you to do this:
1 Stop-Process MyApp
PowerShell performed the task just six times, you’d have paid
off your investment, and every time PowerShell performed
the task after that, you’d be growing the economy. Work would
be happening, essentially for free. That’s how Henry Ford did
it, and that’s why you should care about PowerShell. The
first line on your resume should be, “Dedicated automation
specialist who, in one year, saved former employer $100k [or
whatever] in labor costs.”
Keep a log of what you automate. Figure out how long the task
took to perform manually, and about how many times a year
it was performed. Track the time it took you to automate it.
Figure out the money you saved, and add that to your resume
statement.
That is why you should care about PowerShell.
4. Installing PowerShell
So, this is where we need to make sure we’re all very on board
with terminology.
Windows PowerShell
Windows PowerShell runs on the full .NET Framework, and
runs only on Windows. As of this writing, it’s version 5.1,
although that version will not run on very old versions of
Windows. Windows PowerShell is supported as part of the
operating system it is installed on, which means Microsoft’s
standard OS support policies apply. Windows PowerShell
is installed as part of a package called Windows Manage-
ment Framework (WMF), and you can download that from
http://microsoft.com/powershell. Most versions of Windows
do some with Windows PowerShell preinstalled, although it
might not be the latest version. Within PowerShell, you can
run:
1 PS C:\> $PSVersionTable
PowerShell Core
PowerShell Core is a different piece of software than Win-
dows PowerShell. On Windows systems, you can have both
Windows PowerShell and PowerShell Core installed, and can
even run them side by side. Running this:
1 PS C:\> $PSVersionTable
Will tell you which one you’re currently using, and it’s impor-
tant to keep track. Add-ins and scripts written for Windows
PowerShell won’t always work in PowerShell Core, so you
need to carefully differentiate between them on Windows
systems.
The online docs¹ cover installation instructions for Windows,
various Linux distributions, and macOS. Read the instal-
lation instructions very carefully because there are often
prerequisites you need to install first. That URL defaults to the
Windows installation instructions; links (on the left side, as of
this writing) to the macOS and Linux versions are provided.
In most cases you will need administrator or super-user
access in order to install PowerShell.
¹https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-
powershell-core-on-windows?view=powershell-6
Installing PowerShell 19
VS Code
Windows PowerShell ships with a simple editor called the
Integrated Scripting Environment, or “PowerShell ISE.” This is
technically a deprecated editor; while it still works, Microsoft
isn’t developing it any further. Instead, Microsoft suggests
you use Visual Studio Code, which is a stripped-down, cross-
platform, free editor that can be extended to accommodate
different languages.
Head to https://code.visualstudio.com to download VS Code
for your operating system. You’ll then want to install the
PowerShell Extensions for VS Code, so that VS Code “un-
derstands” PowerShell’s language. Instructions for Windows,
macOS, and Linux are available online.² But basically, once
you’ve got VS Code installed, open it and press Ctrl+P or
Cmd+P. Type ext install powershell, hit Return, and you’ll
see the PowerShell extension. Click its little Install button,
and allow VS Code to Reload after installation finishes.
When you start in VS Code, you’ll want to open a new file
using the File menu, and then immediately save it using one
of PowerShell’s filename extensions. For example, a filename
like Myscript.ps1 or anything else with a .ps1 filename
extension. Saving the file like that is what “tells” VS Code that
this is a PowerShell file, and so it will engage the PowerShell
Extension and start working correctly for the PowerShell
syntax.
²https://docs.microsoft.com/en-us/powershell/scripting/core-powershell/vscode/
using-vscode?view=powershell-6
Installing PowerShell 20
Launch PowerShell
On Windows systems, you can press Windows+R to get the
Run dialog, and then type powershell and hit Return to open
the shell. We find it convenient to pin its icon to the Task bar
once it’s running. On systems with both Windows PowerShell
and PowerShell Core, you may need to dig through the Start
menu to find the one you want to run.
A big note on Windows systems: Normally, PowerShell will
launch as a low-privileged user account, not as Administrator.
However, most of the time, you’ll be performing tasks that
require Administrator permissions. The Windows PowerShell
window title bar will say Administrator if you’re running
with elevated privileges. If you’re not, and you need to, right-
click the Task bar icon and select “Run as Administrator.” This
will open a new window, which should say Administrator in
the title bar.
On macOS and Linux systems, open a command prompt
(that’s the Terminal app on macOS, located in the Application
Your First Console Experience 22
Run a Command
Type Get-Process and hit Return. You should get a big ‘ol
screen full of output, showing all of the apps (including
background ones that you may never have even been aware
of) running on your computer right then.
This is a good time to talk about PowerShell aliases. These are
just nicknames for commands. Like, if you find Get-Process
too hard to type, then you could just type its alias, ps.
Except for one problem. You see, when Windows PowerShell
launched, the product team thought it would be a good idea
to include Unix-like aliases for PowerShell commands. So in
PowerShell, you’d run Get-Process, but on Linux systems the
closest equivalent is ps. Since Windows PowerShell didn’t
run on Linux, this wasn’t a problem. If you were really
familiar with Linux, and you just habitually typed ps, then
PowerShell would do something that was roughly what you
were thinking of.
When PowerShell Core was introduced, though, this created
a conundrum, because ps is a legitimate command on some of
the operating systems where PowerShell Core runs, like Linux
and macOS. If a Linux person sits down at a Linux machine
and types ps, but gets the output of Get-Process instead, that
Linux person is going to be a little irritated. So PowerShell
Core doesn’t define the ps alias on Linux; if you run ps, you’re
getting the really-for-real ps from Linux, not the PowerShell
Get-Process command.
and Linux and macOS. So I’ll just use the full PowerShell
command names, which, thanks to their verb-noun naming
pattern, are pretty easy to distinguish.
But PowerShell command names can be long, and gosh,
typing is just so hard, isn’t it? That’s why aliases were created
in part, right? Because they’re shorter! So rather than subject
you to a lifetime of typing long command names, let me
introduce you to Tab completion. The Tab key, on most
keyboards, is an oversized key toward the upper-left side of
the keyboard. The Tab key is bigger because you’re meant to
use it. It’s easier to hit with your finger, so it’s a convenient
way to make typing shorter.
In PowerShell again, type Get-P, and then hit Tab. PowerShell
will start “filling in” command names that match whatever
you typed up to that point. Keep hitting Tab until Get-Process
shows up, and hit Return. With some practice, you start to
quickly figure out how much you have to type to get what
you need with just one Tab or two.
At this point, you’ve run your first PowerShell command!
It might not feel like it, but you’re well on your way to
mastering this thing!
1 PS /Users/donjones> get-psdrive \
2
3
4 Name Used (GB) Free (GB) Provider Root \
5
6 ---- --------- --------- -------- ---- \
7
8 / 266.04 665.51 FileSystem / \
9
10 Alias Alias \
11
12 Env Environment \
13
14 Function Function \
15
16 Variable Variable
1 Set-Location /
Windows users:
1 Set-Location C:\
1 Get-ChildItem
On any operating system, you could also use the alias dir.
Don’t use ls, though; while it will work as expected on
Windows systems, on Linux and macOS it runs the native ls
command, which is very different. And this is the last time
I’ll bring up aliases! From now on, I’ll just use full command
names and rely on Tab completion to lighten the typing load.
Now, I’m going to change to my “home” folder. This is a thing
PowerShell tracks in its special $home placeholder, so it’ll work
on any operating system.
1 Set-Location $home
Now, we want to make a new folder that we can play in, store
some test files in, and so on. To do that, I’ll use the New-Item
command. This command is capable of creating many types
of new items, and so in addition to the name of the new item,
we’ll have to tell it what kind of item to create. In this case, a
folder, or Directory. You should be able to use Tab completion
to complete most of this:
Your First Console Experience 27
Make sure the final command reads the same as the one above.
You won’t be able to run the command twice, so if you’ve
already done so and you hit Return on the second one, you’ll
get an error, telling you that the 4n00bs directory already
exists:
Don’t let errors panic you too much. Yeah, they’re red, and
they do remind me of every bad English paper we turned in
in high school, but they contain useful information most of
the time. This one is telling us that 4n00bs already exists. It’s
showing us the PowerShell command it had a problem with,
Your First Console Experience 28
Exit
To exit, either type exit and hit Return, or just close the
command-line window.
Built-In Commands
This is one of the first confusing things newcomers run into
with PowerShell, especially Windows PowerShell. There are
Where Do Commands Come From? 30
get all those “server commands.” Which leads nicely into the
second main place commands come from…
The Internet
Of course, you can always just download stuff from the
Internet. Search Google and cross your fingers! Some modules
Where Do Commands Come From? 32
PowerShell Gallery
PowerShellGallery.com is a Microsoft-run repository of Pow-
erShell scripts, modules, and other kinds of resources. It’s
where the cool kids share their PowerShell modules these
days, and it’s the main source we’ll be focusing on here.
You can start by simply visiting the web site and searching
or browsing through the available modules. There are a lot.
But at some point you’re going to want to download some of
them to your computer, to start using them in PowerShell.
1 Find-Module \*html\*
2
3 Version Name Repository \
4
5 ------- ---- ---------- \
6
7 1.0.0.98 ConvertToHtml PSGallery \
8
9 2.1.0.1 EnhancedHTML2 PSGallery \
10
11 1.0.1 Write-HtmlNode PSGallery \
12
13 0.1.1 HtmlReport PSGallery \
14
15 1.4.0.3 ReportHTML PSGallery \
16
17 0.0.1 pshtmltable PSGallery \
18
19 0.0.0.2 ReportHTMLHelpers PSGallery \
20
21 1.2.6 MarkdownToHtml PSGallery \
22
23 0.1.6 PowerHTML PSGallery
Where Do Commands Come From? 34
1 Install-Module EnhancedHTML2
2
3
4 Untrusted repository
5 You are installing the modules from an untrusted re\
6 pository. If
7 you trust this repository, change its InstallationP\
8 olicy value by
9 running the Set-PSRepository cmdlet. Are you sure \
10 you want to
11 install the modules from 'PSGallery'?
12 [Y] Yes [A] Yes to All [N] No [L] No to All [S]\
13 Suspend
14 [?] Help(default is "N"): y
1 Get-Module -ListAvailable
2
3 Directory:
4 /usr/local/microsoft/powershell/6.0.0-beta.3/Mo\
5 dules
6
7
8 ModuleType Version Name
9 ---------- ------- ----
10 Script 2.1.0.1 EnhancedHTML2
11 Manifest 1.1.0.0 Microsoft.PowerShell.Archive
12 Manifest 3.0.0.0 Microsoft.PowerShell.Host
13 Manifest 3.1.0.0 Microsoft.PowerShell.Management \
14 Manifest 3.0.0.0 Microsoft.PowerShell.Security
15 Manifest 3.1.0.0 Microsoft.PowerShell.Utility
16 Script 1.1.4.0 PackageManagement
17 Script 3.3.9 Pester
18 Script 1.1.3.1 PowerShellGet
19 Script 0.0 PSDesiredStateConfiguration
20 Script 1.2 PSReadLine
You can see that we don’t have many, which is because we ran
this in a fairly basic PowerShell Core installation on macOS.
A Windows computer would list many more modules, in most
cases, especially in Windows PowerShell (versus PowerShell
Core). Of especial note is the directory shown near the top of
Where Do Commands Come From? 37
1 $env:PSModulePath
2 /Users/donjones/.local/share/powershell/Modules:/us\
3 r/local/share/powershell/Modules:/usr/local/microso\
4 ft/powershell/6.0.0-beta.3/Modules
What’s in a Module?
Modules consist, for the most part, of commands. There are
actually several kinds of things in PowerShell that are all
considered commands, and since they basically all work the
same, you don’t need to worry much (at this stage) what
the differences are. Try this (assuming you’ve been following
along to this point):
right there, clear as day. You can do this with any installed
module, although some of them contain a lot of commands,
so just be prepared for that to scroll by on the screen!
1 Set-ExecutionPolicy Unrestricted
This will let you follow along with the examples in this book,
and so long as you’re careful and deliberate (meaning, not
hasty), then you’ll be fine. You won’t be “opening up” any
“security holes,” either.
Update Help
Your first step, and a step you should repeat every couple
of months, is to update the local help files stored on your
computer.
1 Update-Help
Now, there are two things that may go wrong here. Here’s the
first one:
The other thing that can, and often does, go wrong is that
help won’t be found online. This is normal and expected.
Many modules simply don’t publish online help updates,
and that’s especially true of non-Microsoft modules. So you
should always read the error message carefully and decide if
it’s actually a problem or not.
You can see that this is a slightly different list, because it’s
looking for help files, not commands. There are no help files
for the built-in applications on the computer, because those
are external to PowerShell, and so they don’t show up on this
list. Here’s another time you’ll see the difference between help
and commands:
1 Get-Help about*
How Do I Use This Thing? 45
We almost always ask for that -Full help, because it’s got so
much more in it.
Online Help
It’s also never a bad idea to punch your favorite command
name into Google or Bing, since the top results will likely be
the web-based version of the help file. That’s especially nice if
you’re working on a system where you don’t have permission
to update help, or if you want the help to appear in a separate
window (making it easy to refer to while you continue to
work in PowerShell).
1 NAME
2 Get-Process
3
4 SYNTAX
5 Get-Process [[-Name] <string[]>] [-Module] [-Fi\
6 leVersionInfo] [<CommonParameters>]
7
8 Get-Process [[-Name] <string[]>] -IncludeUserNa\
9 me [<CommonParameters>]
10
11 Get-Process -Id <int[]> [-Module] [-FileVersion\
12 Info] [<CommonParameters>]
13
14 Get-Process -Id <int[]> -IncludeUserName [<Com\
15 monParameters>]
16
17 Get-Process -InputObject <Process[]> -IncludeUs\
18 erName [<CommonParameters>]
19
20 Get-Process -InputObject <Process[]> [-Module] \
21 [-FileVersionInfo] [<CommonParameters>]
1 -FileVersionInfo
2
3 Required? false
4 Position? Named
5 Accept pipeline input? false
6 Parameter set name Id, InputObjec\
7 t, Name
8 Aliases FV, FVI
9 Dynamic? false
This reinforces what the brackets all spelled out in the more
concise syntax section. This parameter isn’t required, and it
can’t be used positionally - you have to actually write out the
parameter name. It’s a member of three parameter sets.
There’s a trick with parameter names you should know about.
Well, two tricks, really. First, you only ever need to type
enough of the parameter name to distinguish from other
parameters. So typing -FileV would be just as good as the
full -FileVersionInfo. Of course, thanks to the magic of tab
completion, if you typed -FileV you might as well tap the Tab
key and finish the parameter name. Doing so makes it easier
to read! The second trick is that some parameters have aliases,
or nicknames. In this case, we can see that -FV would be just
as good as -FileVersionInfo, in terms of typing. Of course, in
terms of reading, -FV isn’t as descriptive, so we still tend to
recommend using the full parameter name.
Finally, most help files will include a number of helpful
examples, which show you how to use the command. We
can’t stress enough how useful and important these are!
About 90% of the time, when we’re answering questions in
the PowerShell.org forums, the answer was right in the help
file examples all along!
8. Objects and the
Magic of Formatting
One thing that can be a little abstract about PowerShell is this
notion of objects, the structured data that most PowerShell
commands output. The reason it’s a little abstract is that you
can’t easily see the darn things. Here’s why: when you run a
PowerShell command, like this:
1 Get-Process
1 Get-Process | Out-Default
Formatting Rules
So what does this magic, unseen formatting system actually
decide to do with your objects? There’s actually a simple rule
set.
First, the system looks to see what type of structured data it’s
dealing with. In .NET Framework, which is what PowerShell
is built on, every possible type of structured data has a unique
name, appropriately called a type name. The objects output by
Get-Process have the type name System.Diagnostics.Process.
You an see this by running:
1 Get-Process | Get-Member
Once the formatting system knows the type name, it can run
through its rules.
That’s it! There’s only those two rules. Of course, you can
override that behavior anytime you want to. You do this
by intercepting the objects before they make it to the secret
Out-Default command. For example, to force PowerShell to
make a list:
1 Get-Process | Format-List
Try These
We’d like you to try the following, just so you can start to get
a personal idea of how all this works, and what the possibil-
ities are. These will work in both Windows PowerShell and
PowerShell Core, and they’ll work in any version of either.
Spend a few moments reviewing the help files for these com-
mands, because they’re going to be incredibly useful to you as
you move forward with PowerShell. And, more importantly,
spend some time “playing” with these commands, perhaps
by piping Get-Process to them. You’re not going to hurt
anything on your computer, and some unstructured “play
time” will let you experiment, and start building your own
mental model of how these commands work and what they
can do for you.
Objects and the Magic of Formatting 57
Six Pipelines
In actuality, a PowerShell command can stick output into as
many as six “out baskets.” PowerShell doesn’t have stdout or
stdin. Instead, for output, it supports six pipeline “streams”:
1 Get-Process | Get-Member
¹pulluphttps://docs.microsoft.com/en-us/powershell/module/microsoft.
powershell.core/where-object?view=powershell-6
Enter the Pipeline 64
1 -InputObject <psobject>
2
3 Required? false
4 Position? Named
5 Accept pipeline input? true (ByValue)
6 Parameter set name (All)
7 Aliases None
8 Dynamic? false
9
10 -Value <Object>
11
12 Required? false
13 Position? 1
14 Accept pipeline input? false
15 Parameter set name ContainsSet, C\
16 ase…
1 Name
2 pwsh
3 bash
4 httpd
Cool. Let’s run that to Get-Member and see what the type name
is:
Because those are the values in our CSV file. Let’s do it:
Enter the Pipeline 68
Wrapping Up
With traditional shells’ support for a single stdout and stdin,
and with traditional commands’ exclusive use of text for
output and input, pipelining was easy to understand, but
Enter the Pipeline 69
Filtering
Filtering is when you specify some kind of logical criteria, and
PowerShell removes some objects from the pipeline which
don’t meet your criteria. Objects that do meet your criteria
continue on the pipeline to whatever command is next. Or,
if there are no more commands, those “matching” objects are
the ones you end up seeing in the final output.
Consider this:
to work with the objects that were piped in. So $_ was created
as a generic way of referring to “whatever was piped in.” It’s
very important to know that $_ will only work in special
situations where PowerShell has been preprogrammed to look
for $_, and Where-Object’s filter script happens to be one
of those places (there are about half a dozen or so “special”
places, and we’ll point them out as we come to them). You
can also use $PSItem in place of $_ if you find that easier to
read, although you’ll tend to see most people using $_ since
that’s the one PowerShell started with in v1.
We tend to think of $_ as a fill-in-the-blank form field, like
on a tax form.
1 Get-Process |
2 Where { $_.Name -like '*s*' -and $_.Name -notlike '\
3 *d*' }
This will list processes which contain “s” in their name, but
not “d.” This syntax also throws newcomers a lot of the time.
You’ll see people try this, which won’t work:
Filtering and Selecting 74
1 Get-Process |
2 Where { $_.Name -like '*s*' -and -notlike '*d*' }
1 Get-Process |
2 Where { ($_.Name -like '*s*') -and (-notlike '*d*')\
3 }
You can easily see that the second set of parentheses contains
only an operator and one operand; it needs two operands to
be valid:
1 Get-Process |
2 Where { ($_.Name -like '*s*') -and ($_.Name -notlik\
3 e '*d*') }
Give that last one a try and see what it does on your computer.
As a note, you can type it exactly as we’ve shown here, hitting
Return after the vertical pipe character. PowerShell will enter
a kind of “extended prompt” mode, and you just hit Return on
a blank prompt when you’ve finished typing. That signals to
the shell that you’re done, and it’ll execute everything you’ve
typed.
Filtering and Selecting 75
1 Get-Process -Name s*
2
3 Get-Process | Where Name -like "s*"
Selecting Properties
If you remember from the chapter on formatting, PowerShell
has some rules for displaying command’s output objects.
In many cases, one of PowerShell’s configuration files will
specify a default view, which details the properties that Pow-
erShell should display. You’ve also learned that PowerShell’s
Format- commands allow you to override those defaults, and
construct whatever custom lists or tables you want. But you
also learned that the Format- commands basically discard the
original objects, leaving you with formatting directives that
can’t be used for much beyond text file or on-screen output.
For example, try this:
1 Get-Process |
2 Format-Table Name,Id |
3 ConvertTo-HTML |
4 Out-File process-test.html
Filtering and Selecting 77
Now open the resulting HTML file in your web browser and
enjoy the ugly. So how could you make this work the way you
intended? Select-Object (or its alias, Select) is the answer.
1 Get-Process |
2 Select-Object Name,Id |
3 ConvertTo-HTML |
4 Out-File process-test.html
Advanced Selecting
Check this out—it may blow your mind a bit, but we’ll explain
each piece.
1 Get-Process |
2 Select-Object Name,Id,@{name='Proc';expression={$_.\
3 cpu}} |
4 ConvertTo-HTML |
5 Out-File process-test.html
Try it—go ahead and run that, look at the HTML in a web
browser, and then come back here for the explanation.
Filtering and Selecting 78
1 @{name='Proc';expression={$_.cpu}}
So, this new bit showed up in the property list of the Select-Object.
That means we’re actually creating a brand-new property
for each object in the pipeline. This structure is called a
hash table, which consists of name=value pairs. You can
see that this hash table includes two such pairs, named name
and expression. You see, Select-Object has been specially
programmed to understand hash tables containing pairs with
these names (the Format- commands do, also). The command
takes the name pair and creates a new property having that
name—”Proc,” in this instance. To fill in the value for the
new property, the command looks at the expression. The
expression itself is a {script block}, not unlike the filter script
that Where-Object can use. And, like Where-Object, this script
block can use $_ (or $PSItem) to refer to “whatever object was
piped in.”
In this case, we’re taking the Process objects’ native CPU
property, and basically adding a new property called “Proc”
which will contain the CPU value. This is one way to create
custom-looking output if you don’t like one of the objects’
built-in property names.
Wrapping Up
This chapter was meant to get you started with the various
-Object commands by showing you the two most common
Filtering and Selecting 79
1 PS C:\> ./Get-OSInfo.ps1
1 Param(
2 $x
3 )
4 Get-CimInstance -ClassName Win32_OperatingSystem `
5 -ComputerName $x
1 Param(
2 $ComputerName
3 )
4 Get-CimInstance -ClassName Win32_OperatingSystem `
5 -ComputerName $ComputerName
1 Param
2 [Parameter(Mandatory=$True)]$ComputerName
3 )
4 Get-CimInstance -ClassName Win32_OperatingSystem `
5 -ComputerName $ComputerName
The Very Basics of Scripting 83
There, that’s better. And honestly, that’s just about all there
is to it! This script is what we call a controller, in that it isn’t
creating any new functionality, but is instead making it a
bit easier to access a given piece of functionality. Controller
scripts typically just combine a bunch of commands that
you, or someone else (like Microsoft) have written, ensuring
the commands run in the right order and that all the right
parameter values are provided.
It’s also entirely possible to write your very own commands in
PowerShell, and it’s a great way to add new functionality to
the shell. That topic is a bit beyond this book’s scope, though;
we suggest getting into Learn PowerShell Scripting in a Month
of Lunches if you want to tackle that more-advanced topic.
Wrapping Up
Getting into scripting–especially “the right way,” as we’ve
outlined in this chapter–is truly how you take your Power-
Shell skills to “the next level.” It’s how you move from solving
one-off problems to becoming a true automation machine!
12. Going Remote
One cool thing PowerShell offers (and has since v2) is Remot-
ing. Basically, Remoting lets you send commands to a remote
computer, which also runs PowerShell, and have the remote
computer execute those commands. It then sends the results
back to you. This chapter will offer a quick intro to Remoting;
there’s a lot of technical details we’ll gloss over, but you can
find those in the free ebook, Secrets of PowerShell Remoting,
available at https://leanpub.com/secretsofpowershellremoting.
Enabling Remoting
In Windows PowerShell, you’ll find Remoting enabled by
default on server operating systems (e.g., Windows Server).
You have to manually enable it on client operating systems
by running Enable-PSRemoting. For PowerShell–e.g., Pow-
erShell “Core” that runs on macOS, Windows, and Linux–
you’ll usually need to make some decisions about the kind
of connectivity you want to use. Head over to the official
documentation¹ to read up on it.
Connectivity
PowerShell uses its own protocol to “talk” to remote copies of
itself. That protocol is called MS-PSRP, or Microsoft Power-
Shell Remoting Protocol.
¹https://docs.microsoft.com/en-us/powershell/scripting/core-powershell/running-
remote-commands?view=powershell-6
Going Remote 85
PSRP, as its friends call it, can physically connect to the net-
work using two different lower-level protocols. One option,
which is the original one and the most-used in all-Windows
networks, is Web Services for Management, or WS-MAN.
Microsoft implements this protocol in a service called Win-
dows Remote Management, or WinRM; that’s the actual piece
of software that knows how to “talk” WS-MAN. On Win-
dows machines, Enable-PSRemoting will configure WinRM
automagically. Another options, available in PowerShell v6
and later, is to use Secure Shell, or SSH, to convey PSRP
across the network. SSH is the preferred option on mixed-OS
networks, although getting it set up can require a bit of extra
work (the docs we reference above have instructions).
Since this book is targeted at newbies, we’re going to as-
sume that the tricky setup bits are already done in your
environment. This also isn’t intended to be an exhaustive
look at Remoting; the Secrets book we referenced earlier goes
into the gory details, including the security mechanisms that
Remoting uses in different situations.
Remote Jobs
Sometimes, you may need to send long-running, complex
commands to remote computers, and you might not want to
hang around and wait for the results to come in. In those situ-
ations, you can add the -AsJob parameter to Invoke-Command,
and it will run everything on a background thread. You can
then run Get-Job to check the job status, and Receive-Job
to retrieve the final results, once they’re in. The job is “co-
ordinated” by your local computer, and you need to leave
PowerShell running so the remote results will have something
to “come back to.” Once you close your local shell, the job is
essentially terminated.
Going Remote 88
Wrapping Up
As we said, we wanted this to be a short introduction to
Remoting. It’s a big, complex topic, and you can do a lot
with it. Now that you know it exists, and you know it’s core
capability, you can start exploring it more on your own.
13. Understanding
Your OS
When you drive a modern car, you don’t need to know much
about it. The car’s various controls and instruments remove
you from much of the under-the-hood workings. In science
terms, the car abstracts you from the mechanics of the car.
When you want it to “go,” you stomp on the accelerator,
without worrying about the terrifically complex mechanics
that actually result in forward motion.
PowerShell is a little like driving a car that has no dashboard,
no pedals, no transmission shifter, and no steering wheel.
That is, it doesn’t provide very much abstraction on top of
the operating system or whatever other technology product
you’re trying to mess with. If you want the car to “go,” you
need to know exactly which two wires need exactly how
much voltage applied across them in order to correctly signal
the car’s controller computer; too much or too little, and
you could cause a major crash. Same thing with PowerShell.
You’re tinkering with the computer’s brains, and if you’re a
little off, you could lobotomize the whole thing.
In the forums on PowerShell.org (where you’re welcome to
join us), we’re constantly fielding questions that often have
little to do with PowerShell itself, and more to do with the
underlying technology. We still try and answer when we can,
but it’s sometimes hard. For example:
Understanding Your OS 90
purpose troubleshooter.
http://leanpub.com/troubleshooting
1 Get-Process |
2 Format-Table -Prop Name,Id,CPU |
3 ConvertTo-HTML
1 Get-Process |
2 ForEach {
3 $_.Name
4 }
1 $processes = Get-Process
2 ForEach ($proc in $processes) {
3 $proc.Name
4 }
1 $procs = Get-Process
1 $procs.Name
That’d be like walking onto a car lot and saying, “what color
is the car?” The sales guy will probably be, like, “which car,
dude?” You’re standing in a collection of cars, and you haven’t
referenced a particular car. In early versions of PowerShell,
$procs.Name would in fact generate an error, because you’re
trying to get the name of a bunch of things. In current ver-
sions, however, that will work, and it will produce the name
for every process contained in $procs. That’s because newer
versions of PowerShell implicitly enumerate the collection
under the hood, in an attempt to do what it thinks you
probably want. But that makes it more confusing when this
doesn’t work:
The Chapter of Gotchas 96