Prof. Powershell

Perfect PowerShell Properties Part 1: Management Info

Here's how to pull up PowerShell reports for your own use and for others.

One of the most compelling reasons I find to use PowerShell is that I can get at all sorts of management information that used to require arcane or complicated VBScripts and command line tools. Now with a simple command I can easily get the information I need and even better I can also put it in the format I need.

For example, it is pretty easy to get a directory listing using the dir alias for Get-ChildItem.

PS C:\> dir c:\work -file

Directory: C:\work

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---          3/5/2014   2:14 PM        449 admins.csv
-a---         1/23/2014  10:01 AM     131029 chi-hvr2-health-full.htm
-a---         1/22/2014   4:21 PM      32951 chi-hvr2-health.htm
-a---         12/5/2013   4:19 PM        228 ComputerData.xml

But perhaps I'm building a report for someone else to read. The Length property may not be very clear. Instead I want it to be Size. The standard approach is to use a hashtable with Select-Object to create a new property.

PS C:\> dir c:\work -file | Format-Table -Group DirectoryName -property Mode,LastWriteTime,@{Name="Size";Expression={$_.Length}},Name

DirectoryName: C:\work

Mode                LastWriteTime                      Size Name
----                -------------                      ---- ----
-a---               3/5/2014 2:14:43 PM                449 admins.csv
-a---               1/23/2014 10:01:27 AM           131029 chi-hvr2-health-full.htm
-a---               1/22/2014 4:21:37 PM             32951 chi-hvr2-health.htm
-a---               12/5/2013 4:19:42 PM              228 ComputerData.xml
...

I used Format-Table to recreate the output, but usually I would use Select-Object. But let's say you always want to have Size as a property, without going through the extra steps to define it. This is easy to do in PowerShell 3.0 and later.

You can take advantage of PowerShell's extensible type system and easily add a custom property. First, let's see what is currently defined for the file object you get with Get-ChildItem. Use the Get-TypeData cmdlet.

PS C:\> Get-TypeData -TypeName system.io.fileinfo | select -ExpandProperty Members

Key                                Value
---                                -----
VersionInfo                        System.Management.Automation.Runspaces.ScriptP...
BaseName                           System.Management.Automation.Runspaces.ScriptP...
Mode                               System.Management.Automation.Runspaces.CodePro...

These properties were added by PowerShell. It turns out you can easily add your own with Update-TypeData. Let's create an alias property for Length and call it Size.

PS C:\> Update-TypeData -MemberType AliasProperty -MemberName Size -Value Length -TypeName system.io.fileinfo

This command must be run in an elevated PowerShell session. Checking the type data again, we can see the new property.

PS C:\> (Get-TypeData -TypeName system.io.fileinfo | select -ExpandProperty Members).Size

ReferencedMemberName     MemberType                          IsHidden Name
--------------------     ----------                          -------- ----
Length                                                          False Size

I won't see the property in the default display, although I'll show you how to remedy that in another article. But as long as the property is defined, I can use it.

PS C:\> dir c:\work -file | Select Name,Size,LastWriteTime | Out-Gridview -title "Work Files"

You can see the result in Figure 1.

[Click on image for larger view.]  Figure 1.

But wait, it gets better. Maybe sometimes I want to see the size in KB and sometimes in MB. I can create additional properties that will return these calculated properties.

PS C:\> Update-TypeData -MemberType ScriptProperty -MemberName SizeKB -Value {$this.Length/1KB} -TypeName system.io.fileinfo
PS C:\> Update-TypeData -MemberType ScriptProperty -MemberName SizeMB -Value {$this.Length/1MB} -TypeName system.io.fileinfo

Again, once the members are defined you can see them when you pipe a file to Get-Member.

PS C:\> dir c:\work -file | get-member size*

TypeName: System.IO.FileInfo

Name   MemberType     Definition
----   ----------     ----------
Size   AliasProperty  Size = Length
SizeKB ScriptProperty System.Object SizeKB {get=$this.Length/1KB;}
SizeMB ScriptProperty System.Object SizeMB {get=$this.Length/1MB;}

Now I can put them to use.

PS C:\> dir c:\work -file | Select Name,SizeKB,LastWriteTime | Out-Gridview -title "Work Files"

Figure 2 displays the revised output.

[Click on image for larger view.]  Figure 2.

These properties will apply to any file and will last for as long as my PowerShell session is running. To make them always available you would need to add the Update-TypeData commands into your PowerShell profile script.

Right now, I always have to ask for the new property. Next time I'll show you how to change that.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular