So let's put all of these things together.
Some of these examples are variations on other things
I've shown you earlier in the course,
but let's revisit them and make sure we really understand the
PowerShell language and how to put it all together.
So let's create a variable, $os,
and we'll run Get‑CimInstance and get the operating
system class for the computer, Prospero,
and I'm going to get the TotalVisibleMemorySize and
subtract the FreePhysicalMemorySize times 1 KB because I
want to turn this value into bytes.
So $inuse is the total number of bytes of memory that is in
use on Prospero because I want to get some information about
processes running on that computer.
So I'm going to build a hash table of parameters that
I'm going to splat to Get‑CimInstance,
so let's do the ClassName and my ComputerName.
Now I'm going to filter for only processes where the
WorkingSetSize is greater or equal to 250 MB.
When you create a filter, the filter is using legacy syntax,
but it is expecting that value to be in bytes.
By using a subexpression and the 250MB,
I don't have to try to figure out what's the numeric value of 250 MB.
I can just use 250MB, put it as a subexpression,
and PowerShell will fill it out, and expand it,
and plug it into the filter.
With that hash table, I can now splat that to Get‑CimInstance,
so I'm going to @cim, remember, when we splat,
we don't use the dollar sign, we're using the at
symbol, and then select some properties,
and I'm going to actually create some properties here.
So I'm going to grab ProcessID and Name, I'm going to take the WorkingSetSize.
The WorkingSetSize of each property is in bytes,
so I'm going to divide by 1 MB,
and I'm going around that value using the math class and the
round method to 2 decimal points and use that value for a
property I'm going to be calling WorkingMB.
And we do something similar where I'm going to take the WorkingSetSize/$Inuse,
that I created earlier, and create a PctMemory.
In other words, I want to know,
given the processes, what percentage of memory is being used by
each of these processes? And there's my results.
Now, I limited the output to processes greater than 250 MB.
So the PctMemory is a little more meaningful.
If I wanted to,
I could have sorted that output on WorkingMB because that is a number,
and that would have sorted properly.
If I tried to sort on PctMemory, that will sort it as a string,
which in this particular case, would probably work.
But keep that in mind.
When you're using the ‑f operator, you're getting strings not numeric values,
even though it may look like it on the screen.
Let's do something else.
And we get a list of computers from computers.txt,
which is in my work folder,
and this file too has a listing of computers that are misformatted,
so I've got extra spaces and blank lines.
I'm going to use the AND logical operator to say, only take strings
from computers.txt where the length is greater than 0,
we saw that earlier, and Test‑WSMan using the trimmed version of each string,
if that runs successfully,
then I want to keep that name and write to the pipeline,
and that will be saved $n.
So $n right now looks a little funky still, right?
I still have whitespace, but that's fine.
I'm going to clean that up, like this.
I'm going to run Get‑CimInstance, and in this case,
I want the Win32_OperatingSystem, and I'm going to trim,
for the ComputerName,
I'm going to take $n because ComputerName will take
multiple computers and trim each one.
Get‑CimInstance will connect to every computer that's in the list,
and I'm going to repeat myself here in the list because I have
localhosts a couple times and Prospero a couple times.
The Win32_OperatingSystem class has a property,
CSName, which reflects the ComputerName of the object,
so I'm going to make that a property and basically rename it to ComputerName.
I'm going to create another property called OS.
Now, in this particular case,
I'm going to take the Caption property because that has
the value for the operating system,
and I'm going to replace Microsoft with nothing.
Basically,
I'm going to strip off Microsoft so it doesn't say Microsoft
Windows 10, it'll just say Windows 10, for example,
and I'm going to trim any whitespaces that might be left.
I'll then get the Version property as well.
I am now going to create a Timespan that is going to take the
LastBootUpTime from Win32_OperatingSystem instance that I get,
subtracting the current date, and that will become the uptime.
Let's create a property called Installed,
and I'm going to take the InstallDate,
which would normally be just a standard datetime object,
but I'm going to format this using a custom format string,
which will be MMM and then the year.
So the MMM is actually going to give me the month,
or an abbreviation of the month.
You'll see this here in just a second.
Let's create another property called InstallAge.
Instead of using New‑Timespan,
I'm just subtracting. I'll still end up with a Timespan for the
value. And then let's take the TotalVisibleMemory,
divide by 1 MB as an integer,
and you could also do this as an int32. They're really the same thing.
And just to make things a little bit more interesting,
I'm going to send this to a command called Out‑ConsoleGridView.
I have a note in the demo file on what module you need
to install in order to get that.
And there we go.
So that runs absolutely pretty quickly because I'm just querying,
you know, local computer.
So there is Prospero and the localhost, the OS has Microsoft stripped off,
I have the Version, I have my Uptime, I have the install date,
you can see the month abbreviation and the year,
and my InstallAge, and the total memory as an integer.
That looks like a lot of work,
and it took me longer to explain than it probably did to write this.
Once you understand how this all works, it's really not that difficult.
And again,
this is something that you probably would build into
a PowerShell function or script,
but you need to know that it works from the command line first.
Finally, let's try this example.
I'm going to create a Credential object for myself,
put in the password, hopefully I don't mess it up,
and the computer name I want to connect to is Prospero,
which is a remote computer from this session that I'm in,
and I'm going to run Get‑WinEvent, and I'm going to save the result to $data.
So I'm going to do Get‑WinEvent, I'm going to search the system event log,
on the remote computer,
I'm going to pass my Credential object so I can authenticate to Prospero.
The results of Get‑WinEvent, I'm also going to save to a variable,
$all, because in a moment, I'm going to also use that variable.
The results of Get‑WinEvent, I'm then going to group on the providername.
I don't care about what gets grouped.
I just want the count and the providername.
The providername, in this case, will be the source of the event.
I further only care about providers or sources that have created or
generated more than 250 entries in the system event log.
So this may take a moment to run depending on the size of the event log.
So here's $data.
So these are all of the sources and all of the counts.
Now, it doesn't format very well,
but that's fine because I want more information from
Get‑WinEvent than what it can give me.
So I'm going to tell PowerShell, this is what I want,
give it to me, show me what I need to know.
So if we take $data, and for each element that is in that group,
I'm going to create a custom object.
So the source, and just for the sake of demonstration,
I'm going to take that name and make it all lowercase,
I have the count, and I'm going to save that as a custom property,
and now I'm going to create another percentage,
so I'm going to take the count property and divided by $all.count.
Remember,
$all is the variable I created with the Out variable for Get‑WinEvent
because I want to know what percentage of the events are being
generated by each source, and let's include the ComputerName in all
uppercase since I saved it as variable, and let's also create a
property called Report, and I'm just going to get the current date
formatted as a day.
All of that custom output will be sorted on the count property in
descending order, and then to make it easier,
I'm just going to format it as a table. Now, I have a report that
shows me the source of entries in the system event log on Prospero.
If I wanted to, I could save this then to some type of file, I
would strip off the format table, and replace it with the export or
convert command.
But the bottom line is, I got what I needed from PowerShell. Yes,
I had to do a little bit of work.
I had to take advantage of the PowerShell language and syntax,
but because I know it, and eventually, you will know it,
you can do things like this as well.
Almost all of the examples I've shown you in this course,
especially these longer ones, can all become good source material for
your own PowerShell scripts and functions, but again, you need to make sure that they work first properly from the console.