Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Archives
Subscribe
December 2, 2025

An Extended DriveInfo Solution

In this issue:

  • Enhancing the Object Type
    • Adding Aliases
    • Adding Script Properties
    • Adding a Property Set
  • Formatting the Object
    • Adding a Named View
    • Sizes
    • Highlighting DriveType
    • Highlighting Disk Space
  • Summary

At the end of last month I began sharing my solution for the October scripting challenge. I had so much to cover that I ran of space. There are size limits for Gmail which sets a threshold I have to respect. So let's pick up where we left off and see how to take the solution even further.

I left you with a PowerShell function that wrapped around the [System.IO.DriveInfo]::GetDrives() static method. The function creates custom object output with the required properties from the challenge.

The function can work locally:

PS C:\> Get-IoDriveInfo

Name               : C:\
DriveType          : Fixed
DriveFormat        : NTFS
AvailableFreeSpace : 264449970176
TotalSize          : 509722226688
PctFree            : 51.88
VolumeLabel        : Windows
Computername       : CADENZA

Name               : G:\
DriveType          : Fixed
DriveFormat        : FAT32
AvailableFreeSpace : 9332088832
TotalSize          : 16106127360
PctFree            : 57.94
VolumeLabel        : Google Drive
Computername       : CADENZA

Or remotely, and it supports ssh remoting as well.

PS C:\> Get-IoDriveInfo -Hostname fred -user jeff

Name               : /
DriveType          : Fixed
DriveFormat        : btrfs
AvailableFreeSpace : 46003531776
TotalSize          : 51982106624
PctFree            : 88.5
VolumeLabel        : /
Computername       : fred

Name               : /dev
DriveType          : Ram
DriveFormat        : udev
AvailableFreeSpace : 4090560512
TotalSize          : 4090560512
PctFree            : 100
VolumeLabel        : /dev
Computername       : fred
...

> I omitted the password prompt from the output.

Enhancing the Object Type

At this point, I have a working function that meets the basic requirements. This is the point in the development process where great PowerShell scripters separate themselves from good scripters. This is the point where you think about how to elevate your code. What can you do to make it easier for the user to run or consume the output? I spent several articles recently on this very topic so let's apply those concepts here.

I already have a good set of property names.

PS C:\> $a
PS C:\> $a | Get-Member -MemberType Properties

   TypeName: IoDriveInfo

Name               MemberType   Definition
----               ----------   ----------
AvailableFreeSpace NoteProperty long AvailableFreeSpace=264406237184
Computername       NoteProperty string Computername=CADENZA
DriveFormat        NoteProperty string DriveFormat=NTFS
DriveType          NoteProperty DriveType DriveType=Fixed
Name               NoteProperty string Name=C:\
PctFree            NoteProperty double PctFree=51.87
TotalSize          NoteProperty long TotalSize=509722226688
VolumeLabel        NoteProperty string VolumeLabel=Windows

What would make this object easier to use? Here are some ideas.

Adding Aliases

The object is using Name to represent the drive. The user may expect a property called Drive. I can add an alias property for that.

Update-TypeData -TypeName IoDriveInfo -MemberType AliasProperty -MemberName Drive -Value Name -force

Likewise, I may want to make it easier to reference free space and total size.

Update-TypeData -TypeName IoDriveInfo -MemberType AliasProperty -MemberName Freespace -Value AvailableFreeSpace -force
Update-TypeData -TypeName IoDriveInfo -MemberType AliasProperty -MemberName Size -Value TotalSize -force

Adding Script Properties

The object's raw values are in bytes. If the user wants to see sizes in different units, I am forcing them to write an expression like this:

$a | Select Drive,@{Name="SizeGB";Expression={$_.TotalSize/1GB -as [int]}},@{Name="FreeGB";Expression = {[math]::Round($_.AvailableFreespace/1gb,2)}}

Even if you know how to do this, it is tedious to write. A better approach is to add script properties to the object for sizes in MB and GB.

Update-TypeData -TypeName IoDriveInfo -MemberType ScriptProperty -MemberName SizeMB -Value {$this.TotalSize/1mb -as [int]} -force
Update-TypeData -TypeName IoDriveInfo -MemberType ScriptProperty -MemberName SizeGB -Value {$this.TotalSize/1gb -as [int]} -force
Update-TypeData -TypeName IoDriveInfo -MemberType ScriptProperty -MemberName FreeMB -Value {[math]::Round($this.AvailableFreeSpace/1mb,2)} -force
Update-TypeData -TypeName IoDriveInfo -MemberType ScriptProperty -MemberName FreeGB -Value {[math]::Round($this.AvailableFreeSpace/1gb,2)} -force

Now look how easy this becomes:

PS C:\> $a | Select Drive,SizeGB,FreeGB

Drive SizeGB FreeGB
----- ------ ------
C:\      475 246.25
G:\       15   8.69

> This is the type of thing you want to include in help examples.

Notice that all of my references use the native object properties. There isn't a hard rule but I try to avoid using type extensions to define other type extensions.

Adding a Property Set

Another thing to consider is how object properties might be used. It isn't difficult to imagine this as a common use case:

PS C:\> $a | Select-Object Name,Size,Freespace,PctFree,Computername

Name         : C:\
Size         : 509722226688
Freespace    : 264406237184
PctFree      : 51.87
Computername : CADENZA

Name         : G:\
Size         : 16106127360
Freespace    : 9332088832
PctFree      : 57.94
Computername : CADENZA

I can ease the hassle of typing this by creating a property set. If you recall from an earlier article, this requires a .p1xml file. You can create it using New-PSPropertySet from the PSTypeExtensionTools module.

New-PSPropertySet -TypeName IoDriveInfo -FilePath .\IoDriveInfo.types.ps1xml -Name Space -Properties Name,Size,Freespace,PctFree

Once created, I can load the property set using Update-TypeData.

Update-TypeData .\IoDriveInfo.types.ps1xml
Want to read the full issue?
GitHub
Bluesky
LinkedIn
Mastodon
Website favicon
Powered by Buttondown, the easiest way to start and grow your newsletter.