User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

As the versions of Windows PowerShell and PowerShell (not only Windows!) proliferate, it becomes more important to know on which version of PowerShell your shared scripts and modules are running.

Beginning in the open-source versions of PowerShell 6.0-alpha, the version object in $PSVersionTable.PSVersion switched from a System.Version object to a System.Management.Automation.SemanticVersion object.

This is the second article in a series about requiring a particular version of PowerShell. The first is Requiring a Version of PowerShell. In this article, we'll learn about the new SemanticVersion object and explore how to test for and work with SemanticVersion objects.

PSVersion is SemanticVersion

When you start playing around with the new, open-sourced PowerShell 6-alpha on Github (download it here), you might notice that the $PSVersionTable.PSVersion object is not the good old System.Version object that PowerShell has been using since PowerShell 2.0.

Instead, it's a SemanticVersion object that is defined in the new System.Management.Automation.ni.dll, where "ni" stands for "native image."

SemanticVersionObject

 

There's no MSDN help yet for this object, but Jason Shirk assures me that there will be after they settle on how it will work.

SemanticVersionInMSDN

So, what's going on here?

What is Semantic Versioning?

Semantic versioning is really a gift to system administrators, operations managers, and end-users (all of us). It makes version changes understandable and predictable. I'm a big fan.

TIP: To learn about semantic versioning, read the spec. Really. It's not difficult.

The problem with traditional versioning is that it's arbitrary.

On the author side, there are no real rules or much guidance for when to increment a property of the version object. You've made some changes. Do you increment Major, Minor, Build, or Revision? There's probably a lot of the "I worked hard on this, so I'll increment this one." Even when there are internal rules for incrementing version properties, the rules aren't typically communicated to the end-user or shared with other authors.

On the consumer side, you're probably just looking for version changes. Is $newVersion -ge $oldVersion? But, detecting a change doesn't tell you much about the content or importance of the changes. It doesn't tell you much at all, except that one version is later than the next.

Semantic versioning is the solution to this quandary. The specification establishes clear, but not inflexible, guidance for when to increment which property of a semantic version. It provides rules for authors and critical information for consumers.

SemanticVersionRules

When the Label value changes, it's unlikely to affect your business. A change in the Patch value isn't critical, unless a command in a script or module requires that bug fix. Changes in the Minor version are important, especially when you depend on the new feature. And, of course, breaking changes are always significant. Even when they don't affect you immediately, you need to learn about them.

 

How to Require a SemanticVersion

The standard technique for requiring a version of Windows PowerShell is the #Requires -Version directive. #Requires sets only a minimum value, not a required one, and it inspects only the Major and Minor properties of the Version object.

You can use #Requires -Version on PowerShell 6-alpha. PowerShell correctly compares the System.Version object that #Requires -Version takes to the SemanticVersion object. Again, as a minimum version that looks only at the Major and Minor property values. Also, if the #Requires is not the first line in the script, PowerShell runs it first without warning.

#Requires -Version 6.0.1\
"Requires version '6.0.1'"
"Running version $($PSVersionTable.PSVersion)"
PS C:\Program Files\PowerShell\6.0.0.11> C:\Scripts\Test-SemanticVersion.ps1
Requires version '6.0.1'
Running version 6.0.0-alpha

 However, #Requires -Version does not take a SemanticVersion object, even on PowerShell 6-alpha. Only a string that converts to System.Version is valid.

image007

 

And, because the SemanticVersion object is defined in System.Management.Automation.ni.dll, and not in .NET, you cannot create a SemanticVersion object that instantiates the same class on Windows PowerShell 5.1 (or, I haven't figured out how to do that).

So, code like this works on 6-alpha. But, it fails on PowerShell 5.1 and earlier, not because it failed the version requirement, but because it can't create the reference object.

 image009

image011

 

To check for a Patch or Label in a SemanticVersion on a system that might have PowerShell older than 6, use a version string and let PowerShell convert it during the comparison.

image013

image014

 

Just one more caution. When you compare a System.Version object with a Revision value to $PSVersionTable.PSVersion that might contain a SemanticVersion object, be sure to place the Version object on the left of the comparison operator and the SemanticVersion on its right. (PowerShell always converts the second object to the type of the first object.)

If you place the SemanticVersion object on the left, the parsing fails in 6.0.0-alpha because PowerShell cannot convert a Version object with a Revision value to a SemanticVersion object.

#SemanticVersion first fails
$MinimumVersion = '5.1.14393.999'
if ($PSVersionTable.PSVersion -lt $MinimumVersion)
{ throw "This script requires PowerShell $MinimumVersion. Running PowerShell $($PSVersionTable.PSVersion)" }

image017

 

Placing the Version object on the left eliminates the problem.

# Place Version First!
$MinimumVersion = '5.1.14393.999'
if ($MinimumVersion -gt $PSVersionTable.PSVersion)
{ throw "This script requires PowerShell $MinimumVersion. Running PowerShell $($PSVersionTable.PSVersion)" }

Why isn't SemanticVersion changing?

This is all very interesting, but if you've been following the open-source versions from 6.0.0.7 to the current 6.0.0.11, you'll notice that the SemanticVersion has not changed at all. It's still 6.0.0-alpha.

image019

 

The PSVersionTable property that changes between open-source releases is the GitCommitID property, which is just a string. Because the SemanticVersion class isn't yet documented, we don't exactly know, but we probably can guess its use.

image020

 

But, after going to the trouble to switch, oh-so-wisely, from a System.Version object to a SemanticVersion object, why aren't they incrementing it at all?

I had a few minutes to chat with PowerShell team members Kenneth Hansen, Hemant Mahawar, and Jason Shirk about this issue at PowerShell Conference Asia (@PSConfAsia). They explained that they don't have the details of how to use the object completely worked out yet. We're likely to see it implemented, and correctly, in the future, but probably not in the Alpha timeframe.

In the meantime, be aware of the differences, and check that SemanticVersion object.

  June Blender is a technology evangelist at SAPIEN Technologies, Inc. and a Microsoft Cloud and Datacenter MVP. You can reach her at This email address is being protected from spambots. You need JavaScript enabled to view it. or follow her on Twitter at @juneb_get_help.

If you have questions about our products, please post in our support forum.
For licensed customers, use the forum associated with your product in our Product Support Forums for Registered Customers.
For users of trial versions, please post in our Trial Software Questions forum.
Copyright © 2017 SAPIEN Technologies, Inc.