Subscribe via Email

Subscribe via RSS/JSON


Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Naming PowerShell custom objects and setting their default display properties

Learnt a couple of things today. Not in depth, but now I am aware of these features and will explore them in depth someday.

I knew how to create custom objects in PowerShell and I have always tried to return output from my functions/ scripts as custom objects. I was also aware that you can set the default display properties so the output is neater.

Say I create a new object like this:

Notice when I output the object all its properties are output. Usually I may not want that. I may want that only the name property is output and the rest are silent, only shown if asked for.

It’s possible to define the default properties you are interested in. This link gives you more details, the tl;dr summary of which is as follows:

  1. All objects contain a member object called PSStandardMembers which defines the default properties of the object.
  2. The PSStandardMembers object a member object called DefaultDisplayPropertySet. This object contains a property called ReferencedPropertyNames which lists the default displayed properties of the object.
  3. Apart from DefaultDisplayPropertySet you have DefaultKeyPropertySet and DefaultDisplayProperty objects too. I am not sure what DefaultDisplayProperty does but DefaultKeyPropertySet is used when sorting and grouping objects.

To set the PSStandardMembers property of an object one does the following:

Notice now only the properties we specified are shown.

As an aside, and purely because I spent some time trying to figure this out, here’s how DefaultKeyPropertySet influences sorting:

(Thanks to this post which made me realize what DefaultKeyPropertySet does).

Back to DefaultDisplayPropertySet – the problem is that it doesn’t work in PowerShell v2. It’s a bug with PowerShell v2 and this Stack Overflow post gives a workaround which involves creating a temporary ps1xml file for the custom objects and defining its default properties.

I haven’t explored ps1xml files much but the gist of the matter is (1) they are what PowerShell uses to format object output and (2) you can create custom ps1xml files for your custom objects. The Stack Overflow post gives a function that takes an object and an array of properties and sets these properties as the default for that object. It’s a neat function and works as expected, but for a catch …

The catch is that since all custom objects have the same name you can’t set different default properties for different objects. Unless you give a name for the custom object, of course, which differentiates each type of custom object from the other. So how do you go about naming custom objects?

First up, how do you get the current name of an object? From my reflection post we know the following works:

To fiddle with the type name you have to use some hidden members of every object. (This was another new thing learnt today. Didn’t know objects had hidden members too). The way to see these is via Get-Member -Force cmdlet. Have a look at the help for the -Force parameter:

From the help file its clear PSTypeNames is what we are interested in.

The members Clear and Add seem to be what we want:

Instead of clearing the existing types, one can Insert the new type to the top of the list too:

Gotta love it when things fall into place and you have a language that makes it easy to do all these things!

My thanks to this and this post for pointing me towards PSTypeNames.

What is Reflection?

I knew that PowerShell constructs such [bool] – which defines the boolean data type – were called accelerators, but I never knew why and didn’t bother much as I figured I’d learn more about them soon or later.

But yesterday while reading Bruce Payette’s “Windows PowerShell in Action” that book too mentioned the word accelerator without defining it, and so I started Googling a bit about it. This Googling introduced me to accelerators for WMI – very useful, something I must explore sometime – and that got me curious on how to find all the available accelerators in PowerShell. This in turn bought me to the topic of reflection as that’s what one uses to get a list of accelerators in PowerShell.

So what is reflection? Truth to be told it still does not make much sense to be but what I understand is that reflection is the act (or ability) of an object to look at itself (see it’s “reflection” in the mirror so to say) and learn what it’s capable of – what methods it has, what are it’s properties, and so on. And it is useful because sometimes you may encounter objects that you are getting from elsewhere, and reflection is what you need to learn more about the object.

I guess an example will make it clearer.

Say I define an object called $date as below:

As the creator of this object I know it’s of type [datetime]. And since PowerShell provides a cmdlet Get-Members I know I can use it to examine the methods and properties of this object.

But what if I wasn’t the creator of this object. All I know is that I have a script which will get some object as input and I am supposed to examine it and take further action depending on what sort of an object it is. Further, assume the Get-Member cmdlet isn’t available, or for some reason you can’t use it on the object you are receiving (or maybe Get-Member itself depends on reflection, which we’ll talk about below, so it won’t work unless the concept of reflection is supported by PowerShell). Either ways – you don’t have Get-Member available, period.

In such a situation how would you know what is contained inside the object? That’s where reflection comes into the picture.

Before we go further, it’s worth reading this WikiPedia page on reflection, and this and this StackOverflow post. All these links explain reflection, but the takeaway from the Wikipedia page are the examples it gives of reflection in various languages, and the takeaway from one of the answers in the second StackOverflow post is that all objects in Java have a getClass method which lets one reflectively examine an unknown object.

I created a custom PowerShell object to see if PowerShell objects have a similar method.

Sure enough, GetType() looks like what we are after. (GetHashcode() and ToString return an integer and string respectively (as seen from their definitions) so we can straightaway eliminate them).

Let’s dig deeper:

The GetType() method returns an object of type RuntimeType which contains many methods and properties. The interesting bits for us are GetProperties, GetMethods, and so on. Let’s explore these:

Now let’s try this on our “unknown” $date object:

As you can see, without knowing anything about the object we have managed to identify its type, the methods & properties it contains, and even invoke one of the methods. That’s reflection!

Now I have to figure how to use this info to get a list of accelerators in PowerShell. Which is the topic for another post, of course …

Using comma to preserve arrays

I had mentioned earlier that when you pipe an array to the get-member cmdlet the array is unraveled.

While reading Bruce Payette’s excellent “Powershell in Action” book yesterday (and also coincidentally from an unrelated serverfault topic I was reading) I discovered that it’s possible to modify this behavior by prepending a , to the array. Like thus:

Notice it gives the type of the array as well as the various sub-types within it (strings and integers). Useful!

Get-Member quirk

I am sure I mentioned this before (I read it in a blog post somewhere and has usually served me well): Get-Member has a quirk when it comes to arrays in that if you pipe it an array it will give you the members of the elements of the array, not the members of the array itself.

To get the members of the array itself, use the -InputObject parameter: