Windows:如何使用命令行读取可执行文件的版本信息?

34

Windows是否有一个可执行文件,我可以在命令行中运行它来返回可执行文件(.exe)的版本号?

我看到很多不同语言的问题,以及写它的第三方软件的参考资料,但我找不到一个简单的shell命令来做到这一点。如果我不需要安装任何东西,则额外加分。

必须以普通用户身份运行,而不是管理员。


可能是 Command line tool to dump Windows DLL version? 的重复问题。 - josh poley
8个回答

37
wmic datafile where name="C:\\Windows\\System32\\msiexec.exe" get Version /value 
你可以使用wmic命令进行此操作。并且你可以将其包装到批处理文件中。
@echo off
    setlocal enableextensions

    set "file=%~1"
    if not defined file goto :eof
    if not exist "%file%" goto :eof

    set "vers="
    FOR /F "tokens=2 delims==" %%a in ('
        wmic datafile where name^="%file:\=\\%" get Version /value 
    ') do set "vers=%%a"

    echo(%file% = %vers% 

    endlocal

将其保存为(例如)getVersion.cmd,并作为 getVersion.cmd "c:\windows\system32\msiexec.exe" 调用。

编辑以适应评论并不需要管理员权限。在这种情况下,使用混合 cmd / javascript 文件来查询 WMI。同样的用法。

@if (@this==@isBatch) @then
@echo off
    setlocal enableextensions

    set "file=%~f1"
    if not exist "%file%" goto :eof

    cscript //nologo //e:jscript "%~f0" /file:"%file%"

    endlocal

    exit /b
@end
    var file = WScript.Arguments.Named.Item('file').replace(/\\/g,'\\\\');
    var wmi = GetObject('winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2')
    var files = new Enumerator(wmi.ExecQuery('Select Version from CIM_datafile where name=\''+file+'\'')) 

    while (!files.atEnd()){
        WScript.StdOut.WriteLine(files.item().Version);
        files.moveNext();
    };
    WScript.Quit(0)

1
很好,但不幸的是你必须在管理员组中才能运行它 :-( 我需要以我的持续集成用户身份运行它。 - neves
之后如何使用 %vers%?当我尝试运行 echo %vers% 时,命令提示符会告诉我 ECHO is off. - AlainD
@AlainD,setlocal / endlocal 防止环境变量的更改从批处理文件中传播出去。如果您需要 %vers% 值,请将 endlocal 行更改为 enlocal & set "vers=%vers%" - MC ND
@mc-nd 小笔误:enDlocal 和 set "vers=%vers%。 - Andrew Dennison
2
@AndrewDennison,你是对的,谢谢。不幸的是,我不能编辑评论。 - MC ND

31

如果您愿意并且能够使用PowerShell,下面的代码将会起作用。如果您使用的是支持的Windows系统,那么PowerShell将会可用。

(Get-Item -Path 'C:\Program Files\Java\jdk1.8.0_144\bin\java.exe').VersionInfo |
    Format-List -Force
如果您必须在cmd.exe shell中运行它,您可以使用:
powershell -NoLogo -NoProfile -Command ^
    "(Get-Item -Path 'C:\Program Files (x86)\Java\jre1.8.0_201\bin\java.exe').VersionInfo |" ^
        "Format-List -Force"

2
这是最简单和最清晰的答案,直接适用于PS而不需要任何其他依赖。 - not2qubit
@lit 但是在PowerShell 7.2.5中,ProductVersion和FileVersion可以为空。 - user894319twitter
@user894319twitter,pwsh.exe具有以下值:FileVersion: 7.2.5.500,ProductVersion: 7.2.5 SHA: 0aad398b0e918ce7d73dca929ca6395639085b21。没有工具可以控制文件创建者是否将信息放入字段中。我不理解你的观点。 - lit

19
set EXE='c:\firefox\firefox.exe'
powershell "(Get-Item -path %EXE%).VersionInfo.ProductVersion"

虽然这个仅包含代码的回答可能解决了问题,但请添加一些说明为何可以这样做。这将帮助未来用户在自己的情况下评估这个答案。 - Tom Brunberg
8
“添加为什么这样做的解释”是因为它就是被设计成这样的吗?这些模板问题毫无意义。 - bviktor
不行,因为你已经设置了当前活动的exe文件,PowerShell将解释第一行,然后你在当前活动的exe上使用了一个PowerShell命令。 - Overmind
3
什么?我正在几个 Jenkins 作业中积极使用这个代码片段,但请告诉我它为什么不起作用,或者出了什么问题... - bviktor
@bviktor 但是在PowerShell 7.2.5中,ProductVersion和FileVersion可能为空。 - user894319twitter
2
这不是PowerShell的问题,而是可执行文件的问题。如果他们没有填写那个字段,显然你无法查询它。 - bviktor

12

这将仅提供文件版本:

wmic datafile where name='c:\\windows\\system32\\notepad.exe' get version

结果:

Version
6.1.7601.18917

嗨,仅包含代码的答案往往会被标记为需要审核。您能否添加一行说明这段代码的作用呢? - stef
2
这个答案应该排在最前面。简短、精炼、切中要点,更不用说它是有效的,不像当前被接受的答案! - Björn Larsson
有没有一种方法可以不需要传入路径来获取版本,即使用运行命令的目录? - Steve Smith

3
一种方法是使用makecab命令:
; @echo off
;;goto :end_help
;;setlocal DsiableDelayedExpansion
;;;
;;;
;;; fileinf /l list of full file paths separated with ;
;;; fileinf /f text file with a list of files to be processed ( one on each line )
;;; fileinf /? prints the help
;;;
;;:end_help

; REM Creating a Newline variable (the two blank lines are required!)
; set NLM=^


; set NL=^^^%NLM%%NLM%^%NLM%%NLM%
; if "%~1" equ "/?" type "%~f0" | find ";;;" | find /v "find" && exit /b 0
; if "%~2" equ "" type "%~f0" | find ";;;" | find /v "find" && exit /b 0
; setlocal enableDelayedExpansion
; if "%~1" equ "/l" (
;  set "_files=%~2"
;  echo !_files:;=%NL%!>"%TEMP%\file.paths"
;  set _process_file="%TEMP%\file.paths"
;  goto :get_info
; )

; if "%~1" equ "/f" if exist "%~2" (
;  set _process_file="%~2"
;  goto :get_info
; )

; echo incorect parameters & exit /b 1
; :get_info
; set "file_info="

; makecab /d InfFileName=%TEMP%\file.inf /d "DiskDirectory1=%TEMP%" /f "%~f0"  /f %_process_file% /v0>nul

; for /f "usebackq skip=4 delims=" %%f in ("%TEMP%\file.inf") do (
;  set "file_info=%%f"
;  echo !file_info:,=%nl%!
; )

; endlocal
;endlocal
; del /q /f %TEMP%\file.inf 2>nul
; del /q /f %TEMP%\file.path 2>nul
; exit /b 0

.set DoNotCopyFiles=on
.set DestinationDir=;
.set RptFileName=nul
.set InfFooter=;
.set InfHeader=;
.Set ChecksumWidth=8
.Set InfDiskLineFormat=;
.Set Cabinet=off
.Set Compress=off
.Set GenerateInf=ON
.Set InfDiskHeader=;
.Set InfFileHeader=;
.set InfCabinetHeader=;
.Set InfFileLineFormat=",file:*file*,date:*date*,size:*size*,csum:*csum*,time:*time*,vern:*ver*,vers:*vers*,lang:*lang*"

示例输出(它有一个字符串版本,这是对wmic方法的小的补充 :)):
c:> fileinfo.bat /l C:\install.exe
    file:install.exe
    date:11/07/07
    size:562688
    csum:380ef239
    time:07:03:18a
    vern:9.0.21022.8
    vers:9.0.21022.8 built by: RTM
    lang:1033

您还可以查看 tooltipinfo.bat

1

文件版本 c:\windows\system32\notepad.exe(该文件版本预安装在每个Windows操作系统中)。


2
我输入了 where filever 但没有找到任何结果。 - neves
7
显然,filever在Windows 10上已不再可用。虽然OP没有指定操作系统版本,但我会在这里添加评论以供未来读者参考。 - Ro Yo Mi

1

filever.exe在Windows 2003支持工具的SUPPORT.CAB中,也可能在其他地方。

使用VBScript和Scripting.FileSystemObject从CMD脚本中的一种方法。

@Echo off
Set Version=
Echo WScript.Echo "Set Version=" ^& CreateObject("Scripting.FileSystemObject").GetFileVersion("%SystemRoot%\notepad.exe") >%temp%\~FileVer.vbs
Cscript.exe //nologo %temp%\~FileVer.vbs>%temp%\~FileVer.cmd
Call %temp%\~FileVer.cmd
Echo Version=%Version%

一种PowerShell方法的变体,如果您是从CMD脚本调用。 使用FileVersionRaw而不是FileVersion,因为FileVersion可能有额外的文本装饰,但必须ToString()以获得预期格式。
@Echo off
Set Version=
Powershell -c "'Set Version=' + (Get-Command '%SystemRoot%\Notepad.exe').FileVersionInfo.FileVersionRaw.ToString()">%temp%\~FileVer.cmd
Call %temp%\~FileVer.cmd
Echo Version=%Version%

一个从CMD调用的PowerShell方法,用于比较版本号,因为这可能是首次提问的原因。必须使用% ErrorLevel%==x,因为ErrorLevel==x实际上是大于或等于。
@echo off
Powershell -c "exit 10 + ((Get-Command '%SystemRoot%\Notepad.exe').FileVersionInfo.FileVersionRaw).CompareTo([System.Version] '10.0.19041.1')"
If %ErrorLevel%==9  Echo File needs updating
If %ErrorLevel%==10 Echo File is expected version
If %ErrorLevel%==11 Echo File is newer than expected

1
在非提升权限的PowerShell中运行此命令以获取Thunderbird的版本号。
(Get-Item -Path "C:\Program Files\Mozilla Thunderbird\thunderbird.exe").VersionInfo.ProductVersion

它通过从版本信息中过滤出产品版本来输出。 我用chrome.exe进行了测试,也成功了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接