How to (correctly) check file versions with PowerShell

___________________________________________________________________________________________________________________________

IMPORTANT ANNOUNCEMENT FOR OUR READERS!

AskPFEPlat is in the process of a transformation to the new Core Infrastructure and Security TechCommunity, and will be moving by the end of March 2019 to our new home at https://aka.ms/CISTechComm (hosted at https://techcommunity.microsoft.com). Please bear with us while we are still under construction!

We will continue bringing you the same great content, from the same great contributors, on our new platform. Until then, you can access our new content on either https://aka.ms/askpfeplat as you do today, or at our new site https://aka.ms/CISTechComm. Please feel free to update your bookmarks accordingly!

Why are we doing this? Simple really; we are looking to expand our team internally in order to provide you even more great content, as well as take on a more proactive role in the future with our readers (more to come on that later)! Since our team encompasses many more roles than Premier Field Engineers these days, we felt it was also time we reflected that initial expansion.

If you have never visited the TechCommunity site, it can be found at https://techcommunity.microsoft.com. On the TechCommunity site, you will find numerous technical communities across many topics, which include discussion areas, along with blog content.

NOTE: In addition to the AskPFEPlat-to-Core Infrastructure and Security transformation, Premier Field Engineers from all technology areas will be working together to expand the TechCommunity site even further, joining together in the technology agnostic Premier Field Engineering TechCommunity (along with Core Infrastructure and Security), which can be found at https://aka.ms/PFETechComm!

As always, thank you for continuing to read the Core Infrastructure and Security (AskPFEPlat) blog, and we look forward to providing you more great content well into the future!

__________________________________________________________________________________________________________________________

Howdy folks Matthew Reynolds (@MatthewMWR) here. I focus on enterprise Windows optimization and security for Microsoft Services. You might remember me from How Many Coffees Can You Drink While Your PC Starts ( https://channel9.msdn.com/Events/TechEd/NorthAmerica/2014/WIN-B359 ) from TechEd or PowerShell Deep Dives ( http://www.amazon.com/dp/1617291315/ ) from Manning Press.

The following should be simple questions, but I was recently surprised to learn otherwise:

· Did that patch really install?

· Are my servers using the same version of ReallyImportant.dll?

File properties in Explorer has been a reliable one-off method to read version numbers, but in today’s automation-heavy world it’s all about the PowerShell.

Unfortunately the default presentation of file version info in PowerShell is… sub-optimal.

image

What the what? This image shows that for the very same file PowerShell and file properties (Explorer) can report different version numbers. You can try this on various machines and OSes and get fun weird results. Eagle-eyed friends of mine found that on Windows Server 2008 R2 machines with SP1 + additional patches installed PowerShell will show pre-SP1 versions numbers on various DLLs. The example above is from Windows Server 2012 R2.

If you’d like to see this default behavior in PowerShell changed, vote along at https://connect.microsoft.com/PowerShell/Feedback/Details/1027483 .

The workaround

My colleague Artem Pronichkin showed me that VersionInfo contains the information we want. It is just hidden by default.

 

image

Depending on your scripting preferences as a scripty scripter—you can use this freshly revealed truth in several ways.

The following is an example you can copy and paste that exposes the goods as a new property called FileVersionUpdated on all FileInfo objects (in the current session).

Update-TypeData -TypeName System.Io.FileInfo -MemberType ScriptProperty -MemberName FileVersionUpdated -Value {

    New-Object System.Version -ArgumentList @(

        $this.VersionInfo.FileMajorPart

        $this.VersionInfo.FileMinorPart

        $this.VersionInfo.FileBuildPart

        $this.VersionInfo.FilePrivatePart

    )

All FileInfos in my session now have FileVersionUpdated property. Due to default formatting our new property may not appear in some views. You can twiddle with the format descriptors or just use -Property on commands like Format-List as in the following example.

image

 

We can use our new property in scripts or commands to do things like compare versions between machines.

image

Geek mode: PowerShell type adaptation, SxS, and why this is happening

Executable files like EXEs & DLLs are described by several metadata fields including versions, dates, company, and so forth. Some of the fields are updated by patches and some are left alone. File properties (Explorer) and PowerShell were each showing a different subset of the available fields.

Get-Item (among others) in PowerShell returns a FileInfo (http://msdn.microsoft.com/en-us/library/system.io.fileinfo(v=vs.110).aspx) describing the file. For convenience PowerShell tacks on an extra property it calls VersionInfo based on FileVersionInfo (http://msdn.microsoft.com/en-us/library/system.diagnostics.fileversioninfo(v=vs.110).aspx) . FileVersionInfo exposes many fields describing the files. We can get the updated version info if we look at the right fields.

Speaking of metadata, you can get another view into which version is currently presented as being in %WinDir% by using fsutil.exe. The full SxS path also contains a version indicator.

 

image

Now go forth and correctly judge Windows binary version numbers!

Matt “Version Controlled” Reynolds