1
00:00:01,040 --> 00:00:04,810
Now that we've seen some examples of early filtering with parameters,

2
00:00:04,810 --> 00:00:07,640
let's take a look at Where object.

3
00:00:07,640 --> 00:00:10,540
Once again, let's do Get‑Vegetable,

4
00:00:10,540 --> 00:00:14,810
and I'm going to filter this where the color is equal to green,

5
00:00:14,810 --> 00:00:18,440
and I'm using the simplified syntax.

6
00:00:18,440 --> 00:00:20,880
Sure enough, you can see that that works.

7
00:00:20,880 --> 00:00:23,150
Here is the same expression,

8
00:00:23,150 --> 00:00:29,110
but using the more traditional syntax with the script block and $_.

9
00:00:29,110 --> 00:00:31,550
We get the same result.

10
00:00:31,550 --> 00:00:35,430
But remember, you can use any property that you see with Get‑Member,

11
00:00:35,430 --> 00:00:38,200
and sometimes you need to look at Get‑Member

12
00:00:38,200 --> 00:00:41,140
because PowerShell will deceive you.

13
00:00:41,140 --> 00:00:42,280
Here is what I'm talking about.

14
00:00:42,280 --> 00:00:49,330
Let's do Get‑Vegetable, and let's filter where the color is equal to green,

15
00:00:49,330 --> 00:00:54,940
and I want the state to be raw.

16
00:00:54,940 --> 00:00:56,890
Do you see there on the screen?

17
00:00:56,890 --> 00:01:00,920
So I just want the raw vegetables that are green.

18
00:01:00,920 --> 00:01:05,040
Now, why is it cookedstate and not state?

19
00:01:05,040 --> 00:01:09,380
That's because I know from previous experience that the state property that

20
00:01:09,380 --> 00:01:12,700
you see listed there is something that PowerShell has added.

21
00:01:12,700 --> 00:01:15,040
That's not the real property name.

22
00:01:15,040 --> 00:01:19,280
The real property name that I see with Get‑Member is cookedstate,

23
00:01:19,280 --> 00:01:22,440
so that's the value that I need to use.

24
00:01:22,440 --> 00:01:25,870
So I'm going to pipe that result then and Sort on the

25
00:01:25,870 --> 00:01:30,290
Count property in Descending order, and there we go.

26
00:01:30,290 --> 00:01:35,560
So now I have all of the raw green vegetables sorted in

27
00:01:35,560 --> 00:01:40,540
descending order by the number of vegetables.

28
00:01:40,540 --> 00:01:44,540
Let's try an example that's more PowerShell, truly PowerShell related.

29
00:01:44,540 --> 00:01:46,940
Let's use the example from the slides where I'm going to

30
00:01:46,940 --> 00:01:52,480
Get‑Service for all the services that start with W where

31
00:01:52,480 --> 00:01:56,540
the Status is equal to running.

32
00:01:56,540 --> 00:01:56,960
Good.

33
00:01:56,960 --> 00:01:59,940
That worked just the way I wanted it to.

34
00:01:59,940 --> 00:02:03,160
Let's try something maybe that's a little more complex.

35
00:02:03,160 --> 00:02:11,040
Let me save a variable to hold the date for today to a variable called $now.

36
00:02:11,040 --> 00:02:14,950
So what I want to do is I'm going to get a directory listing of my

37
00:02:14,950 --> 00:02:20,700
scripts files Where the CreationTime property,

38
00:02:20,700 --> 00:02:23,540
which is something that I discovered in Get‑Member,

39
00:02:23,540 --> 00:02:26,290
is greater than 7 days ago,

40
00:02:26,290 --> 00:02:30,720
so I'm adding this little .NET trick here that Get‑Date,

41
00:02:30,720 --> 00:02:33,910
which has saved to $now, is a DateTime object.

42
00:02:33,910 --> 00:02:39,570
That DateTime object has an AddDays method, and I'm just subtracting 7 days.

43
00:02:39,570 --> 00:02:41,350
Now, I'm not sure I'm going to get anything,

44
00:02:41,350 --> 00:02:45,140
but hopefully I won't get an error, but let's see what happens.

45
00:02:45,140 --> 00:02:45,720
Oh, good.

46
00:02:45,720 --> 00:02:49,240
Alright, so there are a couple of files there that show up.

47
00:02:49,240 --> 00:02:50,370
And if I wanted to,

48
00:02:50,370 --> 00:02:54,030
I could also have done Get‑ChildItem ‑Recurse to search for all

49
00:02:54,030 --> 00:02:55,820
files because I have some subfolders there,

50
00:02:55,820 --> 00:02:59,040
but you can see that that worked.

51
00:02:59,040 --> 00:03:05,110
So Get‑ChildItem, the first part is limiting the search to just ps1 files,

52
00:03:05,110 --> 00:03:06,360
early filtering.

53
00:03:06,360 --> 00:03:10,420
The second half of that statement is using Where object,

54
00:03:10,420 --> 00:03:14,240
so it's saying, given all of the ps1 files now,

55
00:03:14,240 --> 00:03:17,750
now do the second set of filtering, look at the CreationTime,

56
00:03:17,750 --> 00:03:20,250
and if it's greater or equal to 7 days ago,

57
00:03:20,250 --> 00:03:23,530
keep that file object in the pipeline and send it on,

58
00:03:23,530 --> 00:03:27,440
and that's exactly what it did.

59
00:03:27,440 --> 00:03:30,670
I also want to point out or make sure you understand that you can

60
00:03:30,670 --> 00:03:35,440
use any code you want in that script block.

61
00:03:35,440 --> 00:03:39,660
I have a text file with some servers and my little test domain here,

62
00:03:39,660 --> 00:03:42,170
and I'm going to get the content of that file,

63
00:03:42,170 --> 00:03:44,640
so it's just going to be a list of names,

64
00:03:44,640 --> 00:03:47,840
and I'm going to pipe that to Where object,

65
00:03:47,840 --> 00:03:51,830
and now the script block for this is going to take that

66
00:03:51,830 --> 00:03:54,920
ComputerName from the text file and plug it into the parameter

67
00:03:54,920 --> 00:03:57,070
for ComputerName for Test‑Connection.

68
00:03:57,070 --> 00:04:01,000
This is kind of a PowerShell alternative to ping.

69
00:04:01,000 --> 00:04:07,070
So I'm going to do two pings, and the ‑Quiet will just return true or false.

70
00:04:07,070 --> 00:04:11,880
So what this will do is go through, and if the ComputerName can be pinged,

71
00:04:11,880 --> 00:04:15,470
then pass that name on into the pipeline.

72
00:04:15,470 --> 00:04:21,240
Any code can go in that script block as long as it returns true or false.

73
00:04:21,240 --> 00:04:24,610
And in this case, Test‑Connection with that ‑Quiet parameter,

74
00:04:24,610 --> 00:04:26,280
that's exactly what it's doing.

75
00:04:26,280 --> 00:04:31,340
It's returning either true or false.

76
00:04:31,340 --> 00:04:32,430
Alright, so finally,

77
00:04:32,430 --> 00:04:34,960
let's talk a little bit about this performance

78
00:04:34,960 --> 00:04:37,740
difference I've been talking about.

79
00:04:37,740 --> 00:04:40,780
I'm going to just take a look for discovery purposes.

80
00:04:40,780 --> 00:04:43,890
I'm going to get the win32_process class from Get‑Ciminstance

81
00:04:43,890 --> 00:04:46,970
and just grab a couple to take a look at,

82
00:04:46,970 --> 00:04:48,240
first 5.

83
00:04:48,240 --> 00:04:52,840
So I want to get that WorkingSetSize, and I'm going to do this,

84
00:04:52,840 --> 00:04:53,020
well,

85
00:04:53,020 --> 00:04:56,740
I'll use that text file of ComputerNames. So let's

86
00:04:56,740 --> 00:05:06,150
save the ComputerNames to a variable, and now what I'm going to do is I'm not,

87
00:05:06,150 --> 00:05:07,430
I don't really care about the results,

88
00:05:07,430 --> 00:05:10,010
I want to see how long it takes to get the results,

89
00:05:10,010 --> 00:05:15,240
so I'm going to use a new command called Measure‑Command.

90
00:05:15,240 --> 00:05:21,040
Measure‑Command, you then put whatever code you want to run in a script block,

91
00:05:21,040 --> 00:05:23,600
and it will run the code and then tell you how long

92
00:05:23,600 --> 00:05:25,840
it took for that code to run.

93
00:05:25,840 --> 00:05:30,040
I won't see the results of the command, only the results of how long it took.

94
00:05:30,040 --> 00:05:32,830
I want to measure how long does it take to do

95
00:05:32,830 --> 00:05:40,750
Get‑Ciminstance for all of the server names Where the

96
00:05:40,750 --> 00:05:46,500
WorkingSetSize is greater or equal to 50 MB,

97
00:05:46,500 --> 00:05:51,440
and that took about 252 ms.

98
00:05:51,440 --> 00:05:53,250
Make sure we understand what's going on here.

99
00:05:53,250 --> 00:05:55,540
I'm telling PowerShell,

100
00:05:55,540 --> 00:06:01,080
get all of the Win32 process objects from all, from my four or five servers,

101
00:06:01,080 --> 00:06:03,490
and then filter,

102
00:06:03,490 --> 00:06:09,140
and only keep the ones where the WorkingSetSize is greater or equal to 50 MB.

103
00:06:09,140 --> 00:06:13,040
That took 252 ms.

104
00:06:13,040 --> 00:06:15,640
That's not really the best way to do that.

105
00:06:15,640 --> 00:06:21,940
So let's do it what I think is the better way, the PowerShell way.

106
00:06:21,940 --> 00:06:25,200
So we'll do Get‑CimInstance again, same class,

107
00:06:25,200 --> 00:06:27,950
same number of computers, except this time,

108
00:06:27,950 --> 00:06:32,240
I'm going to apply filtering.

109
00:06:32,240 --> 00:06:35,620
So I'm going to say, using Get‑CimInstance,

110
00:06:35,620 --> 00:06:41,110
query on the server as you're looking at the Win32 processes,

111
00:06:41,110 --> 00:06:42,660
like a SQL query, if you will,

112
00:06:42,660 --> 00:06:47,960
only give me the objects Where the WorkingSetSize is greater or equal to,

113
00:06:47,960 --> 00:06:55,440
and that's the equivalent for 50 MB, that's the value then in bytes,

114
00:06:55,440 --> 00:06:57,350
and that took 66 ms.

115
00:06:57,350 --> 00:06:59,670
So that is significantly faster.

116
00:06:59,670 --> 00:07:02,620
And if you take this idea and scale it out,

117
00:07:02,620 --> 00:07:04,590
if you were doing, say, 100 servers,

118
00:07:04,590 --> 00:07:08,730
you'd really begin to see the benefits of filtering

119
00:07:08,730 --> 00:07:12,240
and doing things the right way.

120
00:07:12,240 --> 00:07:14,570
I can't stress enough the importance of getting into the

121
00:07:14,570 --> 00:07:17,240
habit of using good filtering practices.

122
00:07:17,240 --> 00:07:19,080
You never know when it will truly matter,

123
00:07:19,080 --> 00:07:22,340
so if you do it all the time, you don't have to think about it.

124
00:07:22,340 --> 00:07:25,040
And that brings our time in this course to an end.

125
00:07:25,040 --> 00:07:28,250
The key takeaway here is to learn and embrace the

126
00:07:28,250 --> 00:07:31,340
PowerShell paradigm of objects in the pipeline.

127
00:07:31,340 --> 00:07:33,370
Once you really understand this idea,

128
00:07:33,370 --> 00:07:36,160
you'll find PowerShell easier to use and wonder why

129
00:07:36,160 --> 00:07:38,440
you waited so long to learn it.

130
00:07:38,440 --> 00:07:40,720
Objects aren't complicated or mysterious.

131
00:07:40,720 --> 00:07:44,240
Use Get‑Member and Select‑Object to discover them.

132
00:07:44,240 --> 00:07:48,140
Once you know property names, you can use them everywhere.

133
00:07:48,140 --> 00:07:51,290
In fact, if you master the commands and concepts in this course,

134
00:07:51,290 --> 00:07:53,860
you can tackle just about anything in PowerShell.

135
00:07:53,860 --> 00:07:57,320
Need to work with something new, like Azure or VMware?

136
00:07:57,320 --> 00:07:58,340
Not a problem.

137
00:07:58,340 --> 00:08:00,390
Since you already know how PowerShell works,

138
00:08:00,390 --> 00:08:04,940
all you need to learn are the commands related to that technology.

139
00:08:04,940 --> 00:08:06,810
This course hopefully is a good start,

140
00:08:06,810 --> 00:08:09,640
but there's a lot more fundamentals that you'll need to learn,

141
00:08:09,640 --> 00:08:14,000
so I hope you'll join me in a future course. Thanks for watching.

