182

How can you get the version information from a .dll or .exe file in PowerShell?

I am specifically interested in File Version, though other version information (that is, Company, Language, Product Name, etc.) would be helpful as well.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Emperor XLII
  • 13,014
  • 11
  • 65
  • 75

11 Answers11

223

Since PowerShell 5 in Windows 10, you can look at FileVersionRaw (or ProductVersionRaw) on the output of Get-Item or Get-ChildItem, like this:

(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.FileVersionRaw

It's actually the same ScriptProperty from my Update-TypeData in the original answer below, but built-in now.

In PowerShell 4, you could get the FileVersionInfo from Get-Item or Get-ChildItem, but it would show the original FileVersion from the shipped product, and not the updated version. For instance:

(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.FileVersion

Interestingly, you could get the updated (patched) ProductVersion by using this:

(Get-Command C:\Windows\System32\Lsasrv.dll).Version

The distinction I'm making between "original" and "patched" is basically due to the way the FileVersion is calculated (see the docs here). Basically ever since Vista, the Windows API GetFileVersionInfo is querying part of the version information from the language neutral file (exe/dll) and the non-fixed part from a language-specific mui file (which isn't updated every time the files change).

So with a file like lsasrv (which got replaced due to security problems in SSL/TLS/RDS in November 2014) the versions reported by these two commands (at least for a while after that date) were different, and the second one is the more "correct" version.

However, although it's correct in LSASrv, it's possible for the ProductVersion and FileVersion to be different (it's common, in fact). So the only way to get the updated Fileversion straight from the assembly file is to build it up yourself from the parts, something like this:

Get-Item C:\Windows\System32\Lsasrv.dll | ft FileName, File*Part

Or by pulling the data from this:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName)

You can easily add this to all FileInfo objects by updating the TypeData in PowerShell:

Update-TypeData -TypeName System.IO.FileInfo -MemberName FileVersionRaw -MemberType ScriptProperty -Value {
   [System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName) | % {
      [Version](($_.FileMajorPart, $_.FileMinorPart, $_.FileBuildPart, $_.FilePrivatePart)-join".") 
   }
}

Now every time you do Get-ChildItem or Get-Item you'll have a FileVersionRaw property that shows the updated File Version ...

Jaykul
  • 15,370
  • 8
  • 61
  • 70
  • 10
    And to make this the equivalent of Lars' accepted answer, just use `(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion` – rand0m1 Aug 30 '11 at 16:44
  • 2
    I am intrigued about the `Get-Command` applied to a dll file. Could you elaborate about its effect ? – Stephane Rolland Oct 22 '14 at 12:42
  • Well, in the old days the FileInfo didn't have a "VersionInfo" ScriptProperty like it does now, but the ApplicationInfo object returned by Get-Command included a "FileVersionInfo" ScriptProperty (which is the same as the VersionInfo that's on the FileInfo objects in the newer versions of PowerShell). – Jaykul Nov 14 '14 at 06:27
  • 4
    **Warning** The FileVersionInfo.FileVersion is a string representation that may not be up to date. You should look at FileVersionInfo.FileMajorPart, FileMinorPart, FileBuildPart, FilePrivatePart. See [GetFileVersionInfo() returns wrong file's version information](http://stackoverflow.com/a/28700830/2286801) – bdeem Feb 24 '15 at 17:13
  • good blog post to support @bdeem's point: https://rohnspowershellblog.wordpress.com/2013/12/16/getting-accurate-file-versions/ – yzorg Mar 10 '15 at 14:51
  • This doesn't work when the path contains parenthesis, is e.g. c:\program files (x86)\myfile.dll. The error message is: *The term 'x86' is not recognized as the name of a cmdlet, function, script file, or operable program* How can be "escaped" the parenthesis characters from bad parsing? – mma Jul 29 '19 at 14:31
  • I'm curious how the (presumably more recent) VersionInfo.ProductVersion property factors into this - does it handle this kind of edge case correctly? – Tydaeus Jul 31 '19 at 15:59
  • @mma I would think you're talking about the (Get-Command ...).Version stuff? You just need to put quotes around your file path to avoid the parenthesis being interpreted as a sub-expression (and thus, as a command). – Jaykul Aug 02 '19 at 03:19
  • @Tydaeus the ProductVersion and FileVersion need not be related at all. A file version is the version of the file, while the ProductVersion is the version of the product that the file is distributed with. Usually they're the same, but they can be completely different, depending on the source of the files. At work our files are versioned according to semver, but the product is versioned by the DATE, for marketing reasons ;-) See also https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource – Jaykul Aug 02 '19 at 03:39
  • 1
    @Jaykul To clarify my earlier comment/question: the original answer demonstrates how to get the ProductVersion in PowerShell through some interesting convolutions, because ProductVersion may be more indicative than FileVersion. The original answer makes no mention of the VersionInfo.ProductVersion property, possibly because the answer pre-dates it. Is `(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersion` a newer simpler way to get the same ProductVersion information as documented in the answer? I don't really trust Microsoft to use the term `ProductVersion` consistently. – Tydaeus Aug 02 '19 at 20:31
  • 2
    @Tydaeus It's not new. You can look it up on docs and see how far back it goes (.NET 1.1) . My answer mentions ProductVersion, but the version we're calculating with all that ScriptProperty code is the real FILE Version, not the ProductVersion. They are sometimes the same, but not always. And unfortunately, every real-world example I come up with changes in the next service release of Windows https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.fileversioninfo.productversion – Jaykul Aug 07 '19 at 04:06
  • I originally mentioned it because at the time, the assembly in question had a DIFFERENT FileVersion and ProductVersion, but the calculated file version *happened* to match the ProductVersion. – Jaykul Aug 07 '19 at 04:13
  • As of PS 5.1 (possibly earlier, I didn't check), there are new `VersionInfo` properties `FileVersionRaw` and `ProductVersionRaw`, which work like the ScriptProperty in this answer, so you can just write `(Get-Item SomeFile).VersionInfo.FileVersionRaw`. – zett42 May 16 '22 at 09:38
  • Yeah, @zett42 is right, those were added in PowerShell 5! https://devblogs.microsoft.com/scripting/the-new-raw-file-version-information-in-powershell-5/ – Jaykul Jun 14 '22 at 21:01
175

Since PowerShell can call .NET classes, you could do the following:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo("somefilepath").FileVersion

Or as noted here on a list of files:

get-childitem * -include *.dll,*.exe | foreach-object { "{0}`t{1}" -f $_.Name, [System.Diagnostics.FileVersionInfo]::GetVersionInfo($_).FileVersion }

Or even nicer as a script: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Lars Truijens
  • 42,837
  • 6
  • 126
  • 143
  • 9
    See @Jaykul for a solution that does not require a .NET object. IMHO Jaykul's response should have been selected as the answer :) – Thomas Bratt Dec 11 '08 at 16:28
  • 3
    Although the other answers give shorter commands, all of the ones I tried print out too much info and truncate the file path to "...". The 2nd command in this answer gives just what you need, works for a directory of files, and is formatting in a way that it's easy to see how to modify it to return other info. Just change the .LegalCopyright in the command to .FileVersion. – Dennis Oct 10 '11 at 14:21
  • This is the correct version for .NET EXEs. Jaykul's answer doesn't get the same version. – ashes999 Mar 07 '14 at 15:34
  • That's actually not right. Look at `get-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -force` and compare the FilePrivatePart to the last part of the FileVersion. The FileVersion shows what originally shipped, and not the patched version. This command, on the other hand, shows the patched version number: (get-command C:\Windows\System32\ubpm.dll).Version – Jaykul Nov 14 '14 at 06:36
  • A better example would be the recently patched _C:\Windows\System32\Lsasrv.dll_ ... but the truth is that `(Get-Command ... ).Version` returns the _ProductVersion_ not the _FileVersion_, and sometimes that matters. So for a full solution that actually returns the *updated* FileVersion, check out the Update-TypeData example in my answer below. – Jaykul Nov 14 '14 at 07:51
  • ```log MethodInvocationException: Exception calling "GetVersionInfo" with "1" argument(s): "/home/rokejulianlockhart/PolicyPlus.exe" ``` – rokejulianlockhart Jul 13 '23 at 14:36
59

'dir' is an alias for Get-ChildItem which will return back a System.IO.FileInfo class when you're calling it from the filesystem which has VersionInfo as a property. So ...

To get the version info of a single file do this:

PS C:\Windows> (dir .\write.exe).VersionInfo | fl


OriginalFilename : write
FileDescription  : Windows Write
ProductName      : Microsoft® Windows® Operating System
Comments         :
CompanyName      : Microsoft Corporation
FileName         : C:\Windows\write.exe
FileVersion      : 6.1.7600.16385 (win7_rtm.090713-1255)
ProductVersion   : 6.1.7600.16385
IsDebug          : False
IsPatched        : False
IsPreRelease     : False
IsPrivateBuild   : False
IsSpecialBuild   : False
Language         : English (United States)
LegalCopyright   : © Microsoft Corporation. All rights reserved.
LegalTrademarks  :
PrivateBuild     :
SpecialBuild     :

For multiple files this:

PS C:\Windows> dir *.exe | %{ $_.VersionInfo }

ProductVersion   FileVersion      FileName
--------------   -----------      --------
6.1.7600.16385   6.1.7600.1638... C:\Windows\bfsvc.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\explorer.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\fveupdate.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\HelpPane.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\hh.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\notepad.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\regedit.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\splwow64.exe
1,7,0,0          1,7,0,0          C:\Windows\twunk_16.exe
1,7,1,0          1,7,1,0          C:\Windows\twunk_32.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\winhlp32.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\write.exe
xcud
  • 14,422
  • 3
  • 33
  • 29
19

I realise this has already been answered, but if anyone's interested in typing fewer characters, I believe this is the shortest way of writing this in PS v3+:

ls application.exe | % versioninfo
  • ls is an alias for Get-ChildItem
  • % is an alias for ForEach-Object
  • versioninfo here is a shorthand way of writing {$_.VersionInfo}

The benefit of using ls in this way is that you can easily adapt it to look for a given file within subfolders. For example, the following command will return version info for all files called application.exe within subfolders:

ls application.exe -r | % versioninfo
  • -r is an alias for -Recurse

You can further refine this by adding -ea silentlycontinue to ignore things like permission errors in folders you can't search:

ls application.exe -r -ea silentlycontinue | % versioninfo
  • -ea is an alias for -ErrorAction

Finally, if you are getting ellipses (...) in your results, you can append | fl to return the information in a different format. This returns much more detail, although formatted in a list, rather that on one line per result:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
  • fl is an alias for Format-List

I realise this is very similar to xcud's reply in that ls and dir are both aliases for Get-ChildItem. But I'm hoping my "shortest" method will help someone.

The final example could be written in long-hand in the following way:

Get-ChildItem -Filter application.exe -Recurse -ErrorAction SilentlyContinue | ForEach-Object {$_.VersionInfo} | Format-List

... but I think my way is cooler and, for some, easier to remember. (But mostly cooler).

m-smith
  • 2,943
  • 4
  • 25
  • 39
16

I prefer to install the PowerShell Community Extensions and just use the Get-FileVersionInfo function that it provides.

Like so:

Get-FileVersionInfo MyAssembly.dll

with output like:

ProductVersion   FileVersion      FileName
--------------   -----------      --------
1.0.2907.18095   1.0.2907.18095   C:\Path\To\MyAssembly.dll

I've used it against an entire directory of assemblies with great success.

eperales
  • 468
  • 5
  • 13
David Mohundro
  • 11,922
  • 5
  • 40
  • 44
11

Just another way to do it is to use the built-in file access technique:

(get-item .\filename.exe).VersionInfo | FL

You can also get any particular property off the VersionInfo, thus:

(get-item .\filename.exe).VersionInfo.FileVersion

This is quite close to the dir technique.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wes
  • 111
  • 1
  • 2
  • (get-item \\"$computerName"\"C$\Program Files\Symantec AntiVirus\VPDN_LU.exe").VersionInfo.FileVersion worked for me. I needed to add a computer name from a loop. – Tequila Nov 07 '13 at 16:28
9

This is based on the other answers, but is exactly what I was after:

(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
noelicus
  • 14,468
  • 3
  • 92
  • 111
  • I am intrigued about the `Get-Command` applied to a dll file. Could you elaborate about its effect (before even calling for the property FileVersionInfo) ? – Stephane Rolland Oct 22 '14 at 12:43
  • dll files contain `FileVersionInfo` just as exe files do. Applying this command to the path will get the file version info! – noelicus Oct 22 '14 at 13:23
5
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")
EBGreen
  • 36,735
  • 12
  • 65
  • 85
4

I find this useful:

function Get-Version($filePath)
{
   $name = @{Name="Name";Expression= {split-path -leaf $_.FileName}}
   $path = @{Name="Path";Expression= {split-path $_.FileName}}
   dir -recurse -path $filePath | % { if ($_.Name -match "(.*dll|.*exe)$") {$_.VersionInfo}} | select FileVersion, $name, $path
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chriseyre2000
  • 2,053
  • 1
  • 15
  • 28
2

As EBGreen said, [System.Diagnostics.FileVersionInfo]::GetVersionInfo(path) will work, but remember that you can also get all the members of FileVersionInfo, for example:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo(path).CompanyName

You should be able to use every member of FileVersionInfo documented here, which will get you basically anything you could ever want about the file.

Adam Haile
  • 30,705
  • 58
  • 191
  • 286
1

Here an alternative method. It uses Get-WmiObject CIM_DATAFILE to select the version.

(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version
Knuckle-Dragger
  • 6,644
  • 4
  • 26
  • 41
  • using a share path with spaces in the name, I got "The property 'Version' cannot be found on this object. Verify that the property exists." – AnneTheAgile Feb 13 '15 at 20:01