在 PowerShell 中获取文件版本

Posted

技术标签:

【中文标题】在 PowerShell 中获取文件版本【英文标题】:Get file version in PowerShell 【发布时间】:2010-09-07 00:55:06 【问题描述】:

如何从 PowerShell 中的 .dll.exe 文件中获取版本信息?

我对@9​​87654323@ 特别感兴趣,但其他版本信息(即CompanyLanguageProduct Name 等)也会有所帮助。

【问题讨论】:

【参考方案1】:

现在您可以从 Get-Item 或 Get-ChildItem 获取 FileVersionInfo,但它会显示出厂产品的原始 FileVersion,而不是更新版本。例如:

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

有趣的是,您可以通过以下方式获取更新的(修补的)ProductVersion

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

我在“原始”和“修补”之间做出的区别基本上是由于 FileVersion 的计算方式(see the docs here)。基本上从 Vista 开始,Windows API GetFileVersionInfo 正在从语言中性文件 (exe/dll) 中查询部分版本信息,并从特定语言的 mui 文件中查询非固定部分(每次文件更改时都不会更新) )。

因此,对于像 lsasrv 这样的文件(由于 2014 年 11 月 SSL/TLS/RDS 中的安全问题而被替换),这两个命令报告的版本(至少在该日期之后的一段时间内)是不同的,并且 第二个是更“正确”的版本。

然而,虽然它在 LSASrv 中是正确的,但 ProductVersion 和 FileVersion 可能不同(实际上这很常见)。因此,直接从程序集文件中获取 updated Fileversion 的唯一方法是自己从部件中构建它,如下所示:

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

或者通过从中提取数据:

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

您可以通过在 PowerShell 中更新 TypeData 轻松地将其添加到所有 FileInfo 对象:

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

现在,每次您执行 Get-ChildItemGet-Item 时,您都会有一个 FileVersion 属性来显示更新后的 FileVersion ...

【讨论】:

为了使这等同于 Lars 接受的答案,只需使用 (Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion 我对应用于 dll 文件的 Get-Command 很感兴趣。你能详细说明它的作用吗? 警告 FileVersionInfo.FileVersion 是一个可能不是最新的字符串表示形式。您应该查看 FileVersionInfo.FileMajorPart、FileMinorPart、FileBuildPart、FilePrivatePart。见GetFileVersionInfo() returns wrong file's version information @Jaykul 澄清我之前的评论/问题:原始答案演示了如何通过一些有趣的卷积在 PowerShell 中获取 ProductVersion,因为 ProductVersion 可能比 FileVersion 更具指示性。原始答案没有提及 VersionInfo.ProductVersion 属性,可能是因为答案早于它。 (Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersion 是获取与答案中记录的相同 ProductVersion 信息的更新更简单的方法吗?我真的不相信微软会一直使用ProductVersion 这个词。 @Tydaeus 这不是新的。您可以在文档上查找它,看看它可以追溯到多远(.NET 1.1)?。我的回答提到 ProductVersion,但我们使用所有 ScriptProperty 代码计算的版本是真正的 FILE 版本,而不是 ProductVersion。它们有时是相同的,但并非总是如此。 ? 不幸的是,我提出的每个真实示例都会在 Windows 的下一个服务版本中进行更改? docs.microsoft.com/en-us/dotnet/api/…【参考方案2】:

由于 PowerShell 可以调用 .NET 类,您可以执行以下操作:

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

或者在文件列表中作为noted here:

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

或者更好的脚本:https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/

【讨论】:

请参阅 @Jaykul 以获得不需要 .NET 对象的解决方案。恕我直言,Jaykul 的回答应该被选为答案:) 虽然其他答案给出了较短的命令,但我尝试的所有命令都打印出太多信息并将文件路径截断为“...”。此答案中的第二个命令提供了您需要的内容,适用于文件目录,并且以一种易于查看如何修改它以返回其他信息的方式进行格式化。只需将命令中的 .LegalCopyright 更改为 .FileVersion 即可。 这是 .NET EXE 的正确版本。 Jaykul 的答案没有得到相同的版本。 这其实是不对的。查看get-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -force 并将FilePrivatePart 与FileVersion 的最后一部分进行比较。 FileVersion 显示最初发布的内容,而不是修补版本。另一方面,此命令显示修补后的版本号:(get-command C:\Windows\System32\ubpm.dll).Version 一个更好的例子是最近修补的 C:\Windows\System32\Lsasrv.dll ...但事实是 (Get-Command ... ).Version 返回 ProductVersion 而不是 FileVersion,有时这很重要。因此,对于实际返回 updated FileVersion 的完整解决方案,请查看下面我的答案中的 Update-TypeData 示例。【参考方案3】:

'dir' 是 Get-ChildItem 的别名,当您从具有 VersionInfo 作为属性的文件系统中调用它时,它将返回一个 System.IO.FileInfo 类。所以……

要获取单个文件的版本信息,请执行以下操作:

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     :

对于多个文件:

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

【讨论】:

【参考方案4】:

我知道这已经得到了回答,但是如果有人有兴趣输入更少的字符,我相信这是在 PS v3+ 中编写这个的最短方法:

ls application.exe | % versioninfo
lsGet-ChildItem 的别名 %ForEach-Object 的别名 versioninfo 这是写$_.VersionInfo 的简写方式

以这种方式使用ls 的好处是您可以轻松地调整它以在子文件夹中查找给定文件。例如,以下命令将返回子文件夹中所有名为 application.exe 的文件的版本信息:

ls application.exe -r | % versioninfo
-r-Recurse 的别名

您可以通过添加-ea silentlycontinue 来进一步优化此设置,以忽略您无法搜索的文件夹中的权限错误等内容:

ls application.exe -r -ea silentlycontinue | % versioninfo
-ea-ErrorAction 的别名

最后,如果您的结果中有省略号 (...),您可以附加 | fl 以以不同的格式返回信息。这会返回更多详细信息,尽管格式为列表,而不是每个结果一行:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
flFormat-List 的别名

我意识到这与 xcud 的回复非常相似,因为 lsdir 都是 Get-ChildItem 的别名。但我希望我的“最短”方法能对某人有所帮助。

最后一个例子可以用以下方式手写:

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

...但我认为我的方式更酷,而且对某些人来说更容易记住。 (但大多更酷)。

【讨论】:

【参考方案5】:

我更喜欢安装 PowerShell Community Extensions 并只使用它提供的 Get-FileVersionInfo 功能。

像这样:

Get-FileVersionInfo MyAssembly.dll

输出如下:

产品版本文件版本文件名 -------------- ----------- -------- 1.0.2907.18095 1.0.2907.18095 C:\Path\To\MyAssembly.dll

我已经成功地将它用于整个程序集目录。

【讨论】:

【参考方案6】:

另一种方法是使用内置文件访问技术:

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

您还可以从 VersionInfo 中获取任何特定属性,因此:

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

这与 dir 技术非常接近。

【讨论】:

(get-item \\"$computerName"\"C$\Program Files\Symantec AntiVirus\VPDN_LU.exe").VersionInfo.FileVersion 为我工作。我需要从循环中添加计算机名称。【参考方案7】:

这是基于其他答案的,但正是我所追求的:

(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion

【讨论】:

我对应用于 dll 文件的Get-Command 很感兴趣。您能否详细说明它的效果(甚至在调用属性 FileVersionInfo 之前)? dll 文件包含FileVersionInfo,就像 exe 文件一样。将此命令应用于路径将获取文件版本信息!【参考方案8】:
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")

【讨论】:

【参考方案9】:

我觉得这很有用:

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

【讨论】:

【参考方案10】:

正如 EBGreen 所说,[System.Diagnostics.FileVersionInfo]::GetVersionInfo(path) 会起作用,但请记住,您也可以获取 FileVersionInfo 的所有成员,例如:

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

您应该能够使用此处记录的 FileVersionInfo 的每个成员,这基本上可以为您提供有关该文件的任何信息。

【讨论】:

【参考方案11】:

这里是另一种方法。它使用 Get-WmiObject CIM_DATAFILE 来选择版本。

(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version

【讨论】:

使用名称中包含空格的共享路径,我得到“在此对象上找不到属性'版本'。验证该属性是否存在。”

以上是关于在 PowerShell 中获取文件版本的主要内容,如果未能解决你的问题,请参考以下文章

[powershell]Use powershell to get file hash / 使用powershell获取文件哈希值

如何在 PowerShell 中获取 MD5 校验和

如何在 Powershell 中使用文件命名约定获取文件

在powershell中获取文件名中正则表达式的索引

喜欢在变量中获取 powershell 脚本的输出以在批处理文件中使用

使用 Powershell 脚本获取文件名中日期大于某个特定日期的文件