Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Archives
Subscribe
January 23, 2026

A Custom PSVersionTable Solution

In this issue:

  • A Few Notes on History Streams
  • December 2025 Scripting Challenge
  • Copy Confusion
  • Attack of the Clones
  • Hashtable Updates
    • Operating System Info
    • PowerShell Installation Date
    • Removing Unwanted Entries
  • Hashtable or Object?
  • New-CustomPSVersionTable
  • Adding Custom Formatting
  • Summary

A Few Notes on History Streams

> After publishing my recent issue that explored using alternate data streams to store file history, this I realizes there was a challenge with my code using event subscriptions to automate the update process. Updating the alternate data stream counts as a changed event, so it is possible to have an update loop where each update to the history stream causes another update. Fortunately, in the code I was testing I had set a limit. Do not implement any of the code event subscription code. I have a work around in mind that I will publish later if it works. This is why you should always test in non-production environments first.

> I also want to add that there is no support for alternate data streams in tools such. as OneDrive or DropBox. I verified that my backup solution retains the alternate data streams, but they do not replicate across my OneDrive devices.

December 2025 Scripting Challenge

At the end of last year, I left you with another PowerShell scripting challenge. I asked you to write a PowerShell function to create a customized version of $PSVersionTable. The command should create output in the global scope.

It should meet the following requirements:

  • Allow the user to define the variable name'
  • Allow the user to create a hashtable or a custom object'
  • On Windows systems, update the operating system value from WMI'
  • Add a computername entry'
  • Add the date PowerShell was updated or installed. Hint: Get the command folder last write time.
  • Remove the following entries: WsmanStackVersion,SerializationVersion, and PSRemotingProtocolVersion'
  • The code must run cross-platform'

Write your code to be as efficient as possible, yet still easy to understand. For bonus points, create a custom formatted view for object output.

Copy Confusion

At first glance, this doesn't seem too difficult. I can start with making a copy of $PSVersionTable. However, this won't work the way you think it will. You may have done something like this in the past:

PS C:\> $a = 1
PS C:\> $b = $a
PS C:\> $b = 5
PS C:\> $b
5
PS C:\> $a
1

So you think this should work:

PS C:\> $j = $h
PS C:\> $j

Name                           Value
----                           -----
location                       home
version                        7.5.4
name                           jeff

Watch what happens as I modify the copy.

PS C:\> $j.Add('responding',$True)
PS C:\> $j

Name                           Value
----                           -----
responding                     True
location                       home
version                        7.5.4
name                           jeff

PS C:\> $h

Name                           Value
----                           -----
responding                     True
location                       home
version                        7.5.4
name                           jeff

Attack of the Clones

The original variable is modified as well. create a true copy, you can use the Clone() method.

PS C:\> $h | Get-Member clone

   TypeName: System.Collections.Hashtable

Name  MemberType Definition
----  ---------- ----------
Clone Method     System.Object Clone(), System.Object ICloneable.Clone()

Let me reset my test variables.

PS C:\> $h = @{name='jeff';version=[version]'7.5.4';location='home'}
PS C:\> $j = $h.Clone()
PS C:\> $j

Name                           Value
----                           -----
name                           jeff
location                       home
version                        7.5.4

Now, if I modify the clone, the original remains unchanged.

PS C:\> $j.add('responding',$True)
PS C:\> $j.responding
True
PS C:\> $h.responding
PS C:\>

In my function, I will create a clone of the original $PSVersionTable to work with.

$clone = $PSVersionTable.clone()

Hashtable Updates

The challenge asked to add information about the computer name.

$clone.Add("Computername",[System.Environment]::MachineName)

I'm using the .NET property so that this will work cross-platform.

Operating System Info

On Windows, getting the operating system information is easy with WMI.

if ($isWindows) {
    $clone['OS'] = (Get-CimInstance -ClassName Win32_OperatingSystem -Property Caption).Caption
}

I'm using the -Property parameter to limit the data returned. All I need is the Caption property so why waste resources retrieving all the properties? Every little bit of performance helps.

I wasn't expecting you to get details on non-Windows systems. This would have sufficed.

elseif ($isLinux) {
    $clone['OS'] = 'Linux'
}
elseif ($isMacOS) {
    $clone['OS'] = 'MacOS'
}
Want to read the full issue?
GitHub
Bluesky
LinkedIn
Mastodon
https://jdhitso...
Powered by Buttondown, the easiest way to start and grow your newsletter.