How to (correctly) check file versions with PowerShell

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 ( https://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 (https://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 (https://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