if you are like me and spend most of your day at a PowerShell prompt, anything that simplifies that process is worth the time to learn or set up. Even though I am a decent typist, I am more than happy to find ways to type less at a PowerShell prompt. I already take advantage of tab completion and PSReadline features. But there is always more to be done. Here's the situation, which I think you can relate to.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Let's say that I frequently run a PowerShell command like this from the console prompt.
Get-Childitem c:\work -file | Select-Object -Property "Name","Length","CreationTime","LastWriteTime"
I'm using files, but it could be any command where you repeatedly want the same collection of property names. I could create variable for the property names.
$p = "Name","Length","CreationTime","LastWriteTime"
dir c:\work -file | select $p
But I'd have to remember to always define that variable. I could define this in my PowerShell profile, but there's a better way.
Property Sets
PowerShell's extensible type system (ETS) allows for something called a property set. This is a collection of properties that you can reference by a single property name. The process object from Get-Process includes a few of these by default.
You can try it yourself.
get-Process | Select psconfiguration
Instead of having to type the 4 property names, you only have to type one. Even less is you use tab completion! To ease my typing burden in my sample scenario, I want a property set for file objects.
New-PSPropertySet
Now for the not-so-easy part. Creating other type extensions like an alias property is simple with Update-TypeData. But a property set can only be defined in a .ps1xml file which is then imported using Update-TypeData. Ugh. Who wants to create XML? So I "cheated" and wrote a command to do it for me.
I have updated my PSTypeExtensionTools module to add a new function called New-PSPropertySet. I can use this function to easily create the .ps1xml file. You can install the PSTypeExtensionTools module from the PowerShell Gallery. You will need v1.71 or later.
To create an extension, you need to know the type name. This is what you see when you pipe to Get-Member. Here's how easy it is.
New-PSPropertySet -Typename System.IO.FileInfo -Name TimeSet -Properties "Name","Length","CreationTime","LastWriteTime" -FilePath c:\work\file.types.ps1xml
My property set will be called TimeSet and use the specified properties. You need to use the ps1xml file extension so that you can import it.
Update-TypeData C:\work\file.types.ps1xml
Now I can use this property.
As long as I am at this, I think I'll create some new type extensions with another command from the PSTypeExtensionTools module and then define a new property set.
Add-PSTypeExtension -TypeName system.io.fileinfo -MemberType AliasProperty -MemberName Size -Value Length
Add-PSTypeExtension -TypeName system.io.fileinfo -MemberType ScriptProperty -MemberName ModifiedAge -Value {New-TimeSpan -Start $this.lastwritetime -End (Get-Date)}
New-PSPropertySet -Typename system.io.fileinfo -Name Age -Properties Name,Size,LastWriteTime,ModifiedAge -Append -FilePath C:\work\file.types.ps1xml
I haven't loaded the new property set but I can test the properties.
The module has mechanisms for exporting and importing type extensions using JSON or XML. But since I have a property set, I might as well include the type extensions.
Export-PSTypeExtension -TypeName system.io.fileinfo -MemberName Size,ModifiedAge -Path c:\work\file.types.ps1xml -append
Update-TypeData C:\work\file.types.ps1xml
If you re-import a file that attempts to define an existing extension, PowerShell will throw an exception. There's no ability to force an update when using a .ps1xml file. But the new settings will be created.
Now I can get results with the property names I want, like Size, create new properties like ModifiedAge, and reference a group of properties as a set, like Age. All I need to do is add the Update-TypeData command in my PowerShell profile script.
I hope you find this as useful as I do. Feel free to leave comments or questions.
Thank you for Yet Another Supercalifragilisticexpialidocious article. Please keep them coming.
Great article! As always.
Thanks, this looks super useful. Unfortunately, -TypeName doesn’t seem to like the Exchange type names that I have fed it. For example: Deserialized.Microsoft.Exchange.Data.Directory.Management.ReducedRecipient
Thanks
Try using the normal typename Microsoft.Exchange.Data.Directory.Management.ReducedRecipient. I’ve had success when I import a deserialized object, like with Import-CliXML. Even though the object is technically deserialized, PowerShell still applies the formatting.