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:

1

2

3

4

5

6

7

8

9

10

11

12

# define a hash-table with the properties

PS>$ObjProps=@{name="Rakhesh";age=34;sex="Male";location="Oman"}

# create a new custom object

PS>$blahObj=New-Object-TypeNamePSCustomObject-Property$ObjProps

# output the object

PS>$blahObj

name age sex location

------------------

Rakhesh34Male Oman

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:

All objects contain a member object called PSStandardMembers which defines the default properties of the object.

The PSStandardMembers object a member object called DefaultDisplayPropertySet. This object contains a property called ReferencedPropertyNames which lists the default displayed properties of the object.

Apart fromDefaultDisplayPropertySet 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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

# define an array containing the properties you are interested in

PS>$DefaultProps=@("Name","Sex")

# create a new object of type PSPropertySet using the previously created array

(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.

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

# creating a custom object (which will be used in the examples below)

PS>$blah=New-Object-TypeNamePSCustomObject

# find its name

PS>$blah.GetType().FullName

System.Management.Automation.PSCustomObject

# this too works, but gives you the shortname

PS>$blah.GetType()

IsPublic IsSerial Name BaseType

----------------------------

True False PSCustomObject System.Object

# this too ...

PS>$blah|Get-Member

TypeName:System.Management.Automation.PSCustomObject

Name MemberType Definition

------------------------

Equals Method boolEquals(System.Objectobj)

GetHashCode Method intGetHashCode()

GetType Method typeGetType()

ToString Method stringToString()

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

PS>help Get-Member-ParameterForce

-Force[<SwitchParameter>]

Adds the intrinsic members(PSBase,PSAdapted,PSObject,PSTypeNames)and the compiler-generatedget_ and set_ methods to the display.By default,Get-Member

gets these properties inall views other than"Base"and"Adapted,"but it does not display them.

The following list describes the properties that are added when you use the Force parameter:

--PSBase:The original properties of the.NET Framework objectwithout extension or adaptation.These are the properties defined forthe objectclass and

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:

1

$date=[datetime]"13 March 2013"

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.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

PS>$blah=New-Object-TypeNamePSObject-Property@{Name="Rakhesh";Age=34}

PS>$blah|Get-Member

TypeName:System.Management.Automation.PSCustomObject

Name MemberType Definition

------------------------

Equals Method boolEquals(System.Objectobj)

GetHashCode Method intGetHashCode()

GetType Method typeGetType()

ToString Method stringToString()

Age NoteProperty System.Int32 Age=34

Name NoteProperty System.StringName=Rakhesh

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).

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

# the default behaviour

PS>1,2|get-member

TypeName:System.Int32

...

# my previous workaround was to use the -inputobject parameter

PS>Get-Member-InputObject1,2

TypeName:System.Object[]

...

# you get a similar effect with the , operator

PS>,1,2|gm

TypeName:System.Object[]

...

TypeName:System.Int32

...

PS>,1,"abc",2|gm

TypeName:System.Object[]

...

TypeName:System.String

...

TypeName:System.Int32

...

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

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.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

# piping an array of integers returns the members of integers

PS>1,2|get-member

TypeName:System.Int32

...

# piping an array of characters returns members of the characters

PS>'a','b'|get-member

TypeName:System.String

...

# piping an array of integers and characters returns members of both

PS>'a',1|get-member

TypeName:System.String

...

TypeName:System.Int32

...

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