I suppose this is as good a time as any to go back to PowerShell and let
me demonstrate how you can create custom properties,
custom objects,
and why you're going to find this of value in your PowerShell work.
Working with custom objects and properties is really probably
my favorite part about being in PowerShell.
It almost seems like magic to me.
It may take a bit to get your head around some of these concepts,
but once you understand how they work,
you will find yourself using them all of the time.
Let me give you an example of some ways you can create custom properties
and custom objects and why you might want to do that.
So let's say that I want to use the Get‑TimeZone command,
so here's what it looks like by default,
but, you know, I want a little more than that,
so I'm going to rerun the command,
and I'm going to select all of the properties because I'd like that output,
but I now want to create an additional custom property.
The property name is defined with my custom hash table,
which has two predefined keys, Name and Expression.
So the Name of my property is going to be Computername,
and the Expression will be the code inside the script block,
and in this case, I'm just returning the computername environmental variable.
When I run this,
I now get a custom object really that has all of
the properties from Get‑TimeZone, plus the custom property,
Computername, that I created.
Here's an example that does a little bit more than that.
So let's do Get‑Process,
and I'm going to filter where all the processes have a
working set size greater or equal to 50 MB,
and now I'll start selecting the object properties that I want to keep,
such as Id and Name, and now I'm going to create a custom property.
So I'm going to create a custom property,
and you should start working at trying to decipher
the code that's on the screen here.
So the property name will be called MemoryMB,
the value is the code inside the script blocks,
and I'm taking the current object in the pipeline,
that's a $_, that object's working set property using the alias property,
ws, so I've got $_.ws / 1 MB, that's in parentheses,
so PowerShell will treat that as 1 unit,
and then I'm going to treat that as an int32.
This will have the effect of rounding it to an integer
and eliminating any decimal points.
I'm now going to create another property called Threads that will give me the
count of the number of threads associated with each process,
and now I'm going to create a property called Runtime,
and the value of Runtime will be the current datetime
minus when the process started.
So again, the Starttime is a property of a Process object,
$_ means the current object in the pipeline,
and I'm just referencing the property with that dotted notation.
And then just to make it nice and easy to read,
I'll pipe the whole results to Format‑Table,
and there we go.
So there are all the processes with a working set size greater than 50 MB,
I see my ID, Name, and the custom properties that I created,
MemoryMB.
Because I treated it as an int32, it rounded everything to the nearest integer,
so I get a nice, clean result.
Here's another example about why you need to read the help,
and we're going to do even more with creating things on the fly.
So I'm going to take the numbers 1 through 10 and sort them,
but I'm going to sort them on a custom property that doesn't even exist.
And, in fact, I don't even really have a name for it.
It's just basically going to take each number,
and I'm using the modulo operator.
That's the percent symbol.
This is a math operation,
which will tell you whether there are remaining numbers.
So dividing a number by 2 will give me even numbers first
and then odd numbers because there's no remainder when I
divide by 2 on an even number.
So now I have the numbers 1 through 10 basically
sorted whether they're even or odd, kind of an artificial example,
other than the fact I wanted to show you that there's really no limit
to what you can do with these custom properties.
And again, that $_ modulo 2 is in a script block,
so you can use these script blocks to kind of define things on the fly.
Let me give you another example.
Let's run Get‑ChildItem on my scripts folder and get
just the top‑level directories.
I'm going to sort those top‑level directories this way.
I'm creating a custom property, and in this custom property,
I'm going to get all of the files in each top‑level folder recursively
and then get the count property of all of those files,
and I'm going to then do this sort in descending order.
Then I will select the first 5 objects that come through the pipeline.
So these are the top five directories that have the most files in them.
Again, maybe not something that you need on a production level,
but I want you to understand the process that I used so that
when you need to do something similar, you go,
oh, yeah, Jeff showed me how to create a custom property to sort on,
and you understand how it works and why you might want to use it.
We can do a similar thing with grouping.
So I'm going to get all of my ps1 files,
and I'm going to group the results based on the year of the
LastWriteTime property of the current object in the pipeline.
So every file that comes through, I'm going to group on this custom property,
so now I can see how many items I have and the corresponding year.
So that's creating custom properties.
Let's look now at custom objects.
So I'm going to create a custom object with some new properties.
One of them will be all of the processes.
I'm going to use Get‑CimInstance, I'll do a similar thing for services,
and I just want to get the ones that are running.
That'll take a moment to run.
Now I'm going to create a hash table, so I'm creating a variable,
$hash, to hold the results.
So my first key is going to call the Computername.
I'll use the environmental variable for computername,
I will grab the Version number from the PSVersion table,
here's another example of the dotted notation,
my ProcessCount, I'll do a similar thing with the Services,
and now I'm going to run the Get‑Uptime command,
which is in PowerShell 7, and close the hash table.
So the hash table looks like the hash table that we have seen before.
Now the fun part.
I want to turn this into an actual object.
I can use New‑Object and use the PSObject as the type name,
which is kind of the base, if you will, and then say use the hash table,
$hash, for all of the properties,
and I'm just going to tee this to a variable $new so I can
do something else with it in a moment.
There you go.
So you can see the properties and the names are the same as in the hash table,
but this is structured as an object.
In fact, my pipe $new,
which I saved because I tee‑ed it to Get‑Member, you can see that this
is a System.Management.Automation.PSCustomObject.
There are some advanced ways that you can insert type names,
but for now, we're going to leave it as a generic custom object.
Because it's a custom object, I can write to the pipeline.
So if I wanted to, I could send this to Out‑File,
or Out‑Printer, or Export‑CSV just about anything that I would want to do.
The other way that you could do this,
and the way that I tend to do it when I get into scripting,
would be an approach like this.
So I'm going to create a variable, $obj,
and I'm going to still create a hash table,
but in front of the hash table, I'm putting this pscustomobject type accelerator.
So I'm going to put in my same properties and values that I had before,
still creating the hash table,
except PowerShell knows to create this as a custom object,
and you'll see this here in just a second.
I'm going to go ahead and add the TimeZone to this object, and we'll do Uptime.
So now, what do I have for $obj?
So there's my custom object.
When I created the hash table with New‑Object,
the property names are not in any particular order.
When you use a custom object, as I've done here,
the property names will be displayed in the order that
you entered them into the hash table.
That may make a difference to you as to what you're doing.
There are additional scripting techniques that you can use to format objects.
That's beyond the scope of what we can do here.
But if you need to have some control over the order of the property names,
create a custom object.
And this also is much nicer because I don't have to create the hash table and
then take the second step of creating the custom object.
Let me wrap up by revisiting an example that we just did a moment ago.
I'm going to create a custom object, as it did earlier with Select object,
but this time,
I'm going to create a PSCustomObject using the type
accelerator I just showed you.
So let me get all the processes that are greater than
50 MB for the working set value, use the foreach keyword,
which is another way of looping through a collection of objects.
So for each $p, which would be the current object in the array of $procs,
I am going to create a custom object using the hash table and the
pscustomobject type accelerator we just looked at.
Now I can use the same Select object,
and the hash table values that I used at the beginning of the demo,
I can use them here.
So I'll get the Id, I'll get the name, I'll create my MemoryMB property name,
and I'm using for the value the same code that was in the
Expression block in the Select object.
We can do Threads, we'll get that thread.count again, and the Runtime.
Now, the one difference that I have made,
by the way, versus the previous example with Select object,
Select object was doing this all in line,
so it's using $_, in this case, I'm using the foreach keyword,
so this enumerator allows me to create my own variable, and
that's why I'm using $p, so it's not $_. It's $p.
Now, let's continue on here and get the Computername.
Now, since I hit Enter, PowerShell will process these things and create
a custom object for every item that's in $procs, and there it is. This
is a, to my way of thinking, sometimes an easier way if I'm creating a
custom object, and this is something I use often in my scripting, this
is a much easier way to create an object I think is easier to read than
using Select objects. If you were doing something at the console,
kind of a one‑off,
I need to quickly bang this out, Select object with those hash tables
worked perfectly fine. For more long‑term maintainability,
especially, as I said, when you get the scripting, you
might find this approach much easier.
Always be thinking about objects and working with objects in the
pipeline, Whether you're working with objects in dotted notation or
creating custom properties or custom objects,
this is really important stuff.
Look for ways to take advantage of these things.
I hope you now feel a little more comfortable about knowing what an object is,
how to discover it.
Get‑Member is your friend. Grab the downloads,
give all this to try, and see for yourself.
Thanks for watching this lesson.
So come back for one more fun‑filled module where we learn more about taking advantage and learning about the PowerShell 7 language.