1
00:00:01,040 --> 00:00:04,780
This is how we've used Where‑Objects from the earliest days of PowerShell,

2
00:00:04,780 --> 00:00:08,840
you run some command and then pipe the results to Where‑Object.

3
00:00:08,840 --> 00:00:10,990
Remember, Where‑Object has an alias of where,

4
00:00:10,990 --> 00:00:15,200
which is what you'll typically see in examples. Where‑Object uses

5
00:00:15,200 --> 00:00:19,010
a script block to test if the incoming objects meet some

6
00:00:19,010 --> 00:00:22,730
requirement. The script block can be as complicated or as long as

7
00:00:22,730 --> 00:00:25,050
you need it to be, although, as you might imagine,

8
00:00:25,050 --> 00:00:27,060
simple is usually better.

9
00:00:27,060 --> 00:00:31,170
The $_ character, or set of characters, means the

10
00:00:31,170 --> 00:00:33,440
current object in the pipeline.

11
00:00:33,440 --> 00:00:36,200
Now this script block that you see on the screen is looking at

12
00:00:36,200 --> 00:00:39,820
the status property of each incoming service object and it's

13
00:00:39,820 --> 00:00:41,880
then performing a simple comparison.

14
00:00:41,880 --> 00:00:45,840
Where filters usually use some type of comparison operator.

15
00:00:45,840 --> 00:00:46,720
In this example,

16
00:00:46,720 --> 00:00:50,820
I'm using the ‑eq, or equals, operator. If you need to,

17
00:00:50,820 --> 00:00:53,590
there is a help topic that you should look at to learn

18
00:00:53,590 --> 00:00:56,200
more about comparison operators.

19
00:00:56,200 --> 00:00:57,480
In this example,

20
00:00:57,480 --> 00:01:01,270
if the status property of the service object is equal to running,

21
00:01:01,270 --> 00:01:05,250
Where‑Object will pass that object to the next command in the pipeline.

22
00:01:05,250 --> 00:01:08,040
If it doesn't, it just ignores that object.

23
00:01:08,040 --> 00:01:11,820
Now as I said, the script block can be as complex as you need it to be,

24
00:01:11,820 --> 00:01:15,440
but in the end it has to give you a true or false result.

25
00:01:15,440 --> 00:01:19,760
Only objects that give you a true result are passed on.

26
00:01:19,760 --> 00:01:21,440
Starting a few versions ago,

27
00:01:21,440 --> 00:01:25,920
PowerShell introduced a simplified syntax for Where‑Object. The concept's

28
00:01:25,920 --> 00:01:29,070
unchanged, you're applying some type of filtering test,

29
00:01:29,070 --> 00:01:31,340
but the syntax is relaxed.

30
00:01:31,340 --> 00:01:35,760
You don't use $_ and you don't need to create an explicit

31
00:01:35,760 --> 00:01:38,640
script block with the curly braces.

32
00:01:38,640 --> 00:01:42,540
This type of syntax works fine with simple comparisons.

33
00:01:42,540 --> 00:01:47,240
What you see here is an equivalent version of my previous example.

34
00:01:47,240 --> 00:01:49,540
All you need is the property name.

35
00:01:49,540 --> 00:01:52,540
The $_ is implied.

36
00:01:52,540 --> 00:01:55,130
But Where‑Object is still comparing, in this case,

37
00:01:55,130 --> 00:02:00,810
the status property of each service object, and only passing on those

38
00:02:00,810 --> 00:02:05,870
where the value of status is equal to running. And just to keep you on

39
00:02:05,870 --> 00:02:09,560
your toes, there's yet another way to use Where‑Object. Instead of

40
00:02:09,560 --> 00:02:14,740
using $_ in the script block, you can use $psitem.

41
00:02:14,740 --> 00:02:16,290
The concept is still the same,

42
00:02:16,290 --> 00:02:23,640
but instead of using $_ to represent the object, you can use that $psitem.

43
00:02:23,640 --> 00:02:26,220
However, as I'd like to say in PowerShell,

44
00:02:26,220 --> 00:02:29,240
just because you can do something doesn't mean you should.

45
00:02:29,240 --> 00:02:32,340
Personally, I'm not a big fan of $psitem.

46
00:02:32,340 --> 00:02:34,310
I suggest that you stick with the traditional

47
00:02:34,310 --> 00:02:37,740
syntax using a script block and $_.

48
00:02:37,740 --> 00:02:41,940
When you find examples online and in the PowerShell help, this is most

49
00:02:41,940 --> 00:02:45,650
likely what you're going to find anyway. It works everywhere,

50
00:02:45,650 --> 00:02:47,230
and when you get to scripting,

51
00:02:47,230 --> 00:02:49,740
this is definitely the form that I would recommend.

52
00:02:49,740 --> 00:02:52,520
Plus, if your filtering expression is going to be complex,

53
00:02:52,520 --> 00:02:54,760
such as the one I have here on the screen, then you

54
00:02:54,760 --> 00:02:59,540
have no choice but to use this syntax, so why not just use it all the time?

55
00:02:59,540 --> 00:03:01,220
Still, as you gain experience,

56
00:03:01,220 --> 00:03:03,990
if you want to use the simple syntax of the prompt for a

57
00:03:03,990 --> 00:03:07,440
simple comparison to save some typing, go right ahead.

58
00:03:07,440 --> 00:03:08,090
Finally,

59
00:03:08,090 --> 00:03:11,550
don't be surprised if you find yourself combining early and

60
00:03:11,550 --> 00:03:14,040
late filtering ideas in the same command.

61
00:03:14,040 --> 00:03:16,620
The first part of the command with Get‑Service is using the

62
00:03:16,620 --> 00:03:21,330
‑name parameter to limit or filter initial results to services

63
00:03:21,330 --> 00:03:23,240
with the name that starts with w.

64
00:03:23,240 --> 00:03:26,350
This small number of service objects is then passed to

65
00:03:26,350 --> 00:03:29,910
Where‑Object to filter again to only show services that are

66
00:03:29,910 --> 00:03:32,430
running and have a manual start type.

67
00:03:32,430 --> 00:03:36,100
Now, this is an admittedly artificial example, but the point I'm trying

68
00:03:36,100 --> 00:03:40,040
to make is that you need to get in the habit of filtering early and using

69
00:03:40,040 --> 00:03:43,830
Where‑Object when you have no other choices. Get‑Service doesn't have an

70
00:03:43,830 --> 00:03:45,210
option to filter on the status,

71
00:03:45,210 --> 00:03:49,100
so I really have no choice but to use Where‑Object. What I

72
00:03:49,100 --> 00:03:52,140
don't want to see are examples like this.

73
00:03:52,140 --> 00:03:53,970
These are things that I've seen from beginner

74
00:03:53,970 --> 00:03:56,340
PowerShell students over the years.

75
00:03:56,340 --> 00:03:57,970
Yeah, these commands will work,

76
00:03:57,970 --> 00:04:00,580
but that doesn't mean it's the right way. For something like

77
00:04:00,580 --> 00:04:03,240
getting services on the local machine, it really won't make

78
00:04:03,240 --> 00:04:05,340
any difference performance‑wise.

79
00:04:05,340 --> 00:04:07,620
But I want you to get in the habit of filtering the

80
00:04:07,620 --> 00:04:11,840
right way, the PowerShell way, because eventually it will matter.

81
00:04:11,840 --> 00:04:15,760
Building good PowerShell practices that you use all the time will go a

82
00:04:15,760 --> 00:04:21,000
long way in helping you get the most out of PowerShell, and I think you'll find it easier to use.

