PowerShell is a very flexible scripting language that allows users to dynamically create and/or extend objects with additional methods and properties. This is very useful when you’re trying to build up a rich data set with all of the properties or methods you need. One important thing that is often overlooked when people are writing scripts that do this is that they can also give those objects a type name. Why is this type name important? Three reasons:
- If you want to further extend those types automatically via a type data file, you’ll want a unique type name so that only the appropriate objects are extended.
- If you want to apply specific default custom formatting to those types via a format data file, you’ll want a unique name so that only the appropriate objects are formatted this way.
- If you want to associate specific links and actions with your custom object type in PowerGUI, you’ll want a unique name so that you don’t get links and actions associated with other types.
In practice there are only two use cases where I need to create a custom object type name, and I apply different names depending on the scenario I’m working with at the time.
If I have created a brand new generic PSObject, then I apply a name appropriate to the object. In this case, after I created my custom object and added the properties, I would do the following:
Alternatively, if I am extending an object of a particular type, then I apply an extended type name for that object to the modified version. In this case, after I created my custom object and added the properties, I would do the following:
$derivedTypeName = $myObject.PSObject.TypeNames
Then if you create type or format data files, you simply need to use your new type name in appropriate XML attribute to set up the association. Or if you’re adding functionality to PowerGUI, any links and actions you create will automatically be associated with the lowest derived object type, which will be the type name you applied to the object before outputting it in the PowerGUI data grid.
You can add as many type names as you want to your objects, so if you want to create a virtual object hierarchy with your custom object types, and then associate format or type data specifications with derived or base object types, you can do that as well through multiple calls to the Insert method on the TypeNames collection. This can be useful if you want to share a certain set of functionality between two types of objects you are creating but in addition you want some functionality to be specific to each type and you don’t want to duplicate code.
Hopefully this will encourage you to name your custom object types and define their default properties in scripts that you share with others.
If you’re working with custom objects you should also check out the follow-up post to this that resulted from Hal’s comments on this post, titled “Essential PowerShell: Define default properties for custom objects“.
|Share this post:|
14 thoughts on “Essential PowerShell: Name your custom object types”
This is a really cool technique, Kirk, thanks. The only thing I regret is that type formatting must be done via external files. I suppose you could generate a ps1xml inline and call it but that ought not be necessary.
You know what, I started typing in a reply saying that someone should create one or more scripts, functions, cmdlets, etc. to handle this sort of thing, and then it dawned on me that in many cases, if not the majority, you don’t even really need it. I mean, realistically, when you create a custom object all you really care about are the default properties to display in your output, right? You’re already adding your own members on the fly, so you don’t really need a types.ps1xml file, and any other formatting you would want to apply can be done using expressions in the Format-Table or Format-List cmdlet. Thanks for making me think twice about this and check out this follow-up post: https://poshoholic.com/2008/07/05/essential-powershell-define-default-properties-for-custom-objects/!
[…] PowerShell: Define default properties for custom objects After posting my blog entry about naming your custom object types on Thursday, Hal Rottenberg left me a comment saying how it’s a shame that you have to […]
[…] From Poshoholic: Essential PowerShell: Name your custom object types […]
great to see somebody else caring about this and using this technique. I thought i was the only one.
Great tip! I have a lot of functions that return lists of datarows. By adding a typename that is more descriptive, I can create formats and type definitions for them in ps1xml files. Makes things look a lot nicer.
[…] You can associate an action with a tree node (rather than the object type) by manually adding your own special type to the objects your node emits: e.g. $myObject.PSObject.TypeNames.Insert(0,'MyObjectTypeName') – see this post for more information on manipulating PowerShell types. […]
[…] Naming Custom Objects […]
Thanks for the help. It Helped to accomplish my goal but i had to correct a few things
Glad it helped. What did you have to correct?
[…] thanks to this and this post for pointing me towards […]
I happened to stumble across this, and it was very helpful. However, when I try to add a new TypeName to an existing object (a PSCustomObject in PS3), I am still unable to use the custom format.ps1xml file. I have tried inserting an extended typename of the base derived type. When I try to pipe the object to Format-Table -view myview, I get an error saying:
ft : The view name myview cannot be found. There are no existing Table views for System.Management.Automation.PSCustomObject objects.
What am I doing wrong?
Without looking at your code, I can only offer a few suggestions where there may be problems in how things are set up. In your format.ps1xml file, is the type name that you enter in that document the exact same type name that appears in the PSTypeNames property for the custom object? You can check the PSTypeNames property on your custom object by creating the object, storing it in a variable, and then invoking $variable.PSTypeNames, where $variable is the name of your variable where you stored the object. Those two type names must be an exact match in order for the format to be applied. If that doesn’t help, I could look at the code and probably identify the issue much more quickly than going back and forth in these comments. My email address is the name of this blog at gmail.com. If you’re still stuck, feel free to send me what you have and I will take a look.
Thanks Kirk. Email sent.