【问题标题】:How do I retrieve the version of a file from a batch file on Windows Vista?如何在 Windows Vista 上从批处理文件中检索文件的版本?
【发布时间】:2010-12-14 23:32:37
【问题描述】:

二进制文件中嵌入了一个版本 - 易于在 Windows 资源管理器中显示。

如何从批处理文件中检索该文件版本?

【问题讨论】:

标签: windows-vista batch-file version


【解决方案1】:

这是一个使用 FileVersionInfo 的solution in PowerShell

【讨论】:

    【解决方案2】:

    我认为filever 是您所需要的。它可以同时获取多个项目的文件版本,并定位大小或版本号不同的文件(例如EXE、DLL)。

    【讨论】:

    • 默认不安装这个。
    • 这适用于 32 位,但似乎无法处理 64 位文件
    【解决方案3】:

    Sysinternals Suite 签出sigcheck.exe。这是一个命令行实用程序,可显示文件版本号、时间戳信息和数字签名详细信息。

    【讨论】:

    • 根据 MSDN 在较新的 Windows 操作系统上将不支持 Filever,所以谢谢。
    【解决方案4】:

    以及无需外部工具的三种方式

    1.WMIC

    WMIC DATAFILE WHERE name="C:\\install.exe" get Version /format:Textvaluelist
    

    注意文件名的双斜线。

    准备使用脚本:

    @echo off
    :wmicVersion pathToBinary [variableToSaveTo]
    setlocal
    set "item=%~1"
    set "item=%item:\=\\%"
    
    
    for /f "usebackq delims=" %%a in (`"WMIC DATAFILE WHERE name='%item%' get Version /format:Textvaluelist"`) do (
        for /f "delims=" %%# in ("%%a") do set "%%#"
    )
    
    if "%~2" neq "" (
        endlocal & (
            echo %version%
            set %~2=%version%
        )
    ) else (
        echo %version%
    )
    

    2.MAKECAB 由于 WMIC 未安装在家庭版本的 Windows 上,因此使用 makecab 的方法可以在每台 Windows 机器上运行:

    ; @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
    

    3 使用 shell.application 和混合批处理\jscript.Here's tooptipInfo.bat

    @if (@X)==(@Y) @end /* JScript comment
        @echo off
    
        rem :: the first argument is the script name as it will be used for proper help message
        cscript //E:JScript //nologo "%~f0" %*
    
        exit /b %errorlevel%
    
    @if (@X)==(@Y) @end JScript comment */
    
    ////// 
    FSOObj = new ActiveXObject("Scripting.FileSystemObject");
    var ARGS = WScript.Arguments;
    if (ARGS.Length < 1 ) {
     WScript.Echo("No file passed");
     WScript.Quit(1);
    }
    var filename=ARGS.Item(0);
    var objShell=new ActiveXObject("Shell.Application");
    /////
    
    
    //fso
    ExistsItem = function (path) {
        return FSOObj.FolderExists(path)||FSOObj.FileExists(path);
    }
    
    getFullPath = function (path) {
        return FSOObj.GetAbsolutePathName(path);
    }
    //
    
    //paths
    getParent = function(path){
        var splitted=path.split("\\");
        var result="";
        for (var s=0;s<splitted.length-1;s++){
            if (s==0) {
                result=splitted[s];
            } else {
                result=result+"\\"+splitted[s];
            }
        }
        return result;
    }
    
    
    getName = function(path){
        var splitted=path.split("\\");
        return splitted[splitted.length-1];
    }
    //
    
    function main(){
        if (!ExistsItem(filename)) {
            WScript.Echo(filename + " does not exist");
            WScript.Quit(2);
        }
        var fullFilename=getFullPath(filename);
        var namespace=getParent(fullFilename);
        var name=getName(fullFilename);
        var objFolder=objShell.NameSpace(namespace);
        var objItem=objFolder.ParseName(name);
        //https://msdn.microsoft.com/en-us/library/windows/desktop/bb787870(v=vs.85).aspx
        WScript.Echo(fullFilename + " : ");
        WScript.Echo(objFolder.GetDetailsOf(objItem,-1));
    
    }
    
    main();
    

    用于 cmd.exe :

    C:\Windows\System32\cmd.exe :
    File description: Windows Command Processor
    Company: Microsoft Corporation
    File version: 6.3.9600.16384
    Date created: ?22-?Aug-?13 ??13:03
    Size: 347 KB
    

    【讨论】:

    • wmic 效果很好。我已经在 win server 2012 和 windows 8 上试过了。
    • 如果有人还在阅读这个线程 - 我正在尝试在 CMD 文件中使用 WMIC 方法,将 WMIC 输出重定向到文件,然后使用 FOR 解析输出。然而,这完全失败了,因为输出文件是 UCS-2 LE BOM(根据 Notepad++)。如果我手动将其转换为 ASCII 它工作正常。我也尝试过不使用文件直接解析命令输出,但这也失败了,大概是出于同样的原因。有人有什么想法吗?
    • @Dave - check this 明天我会更新答案。
    • 感谢 npocmaka,我需要详细研究这一点,但我认为我的问题与额外的 CR 无关。我正在使用 WMIC 获取文件版本:(WMIC DATAFILE WHERE name="blahblah" get Version /format:Textvaluelist) 并使用 'delims==' 进行解析。 WMIC 的输出是 'Version=7.0.0.1' 但我根本没有从 FOR 得到任何回报。另外,我查找了您的更新,但您链接到的 dostips 论坛上的最新帖子是 2014 年 4 月 14 日,我根本找不到您的名字。我错过了什么吗??
    • @Evvo - 在这一行设置 for /f "delims=" %%# in ("%%a") do set "%%#" 。 Version=something 是已处理字符串的一部分。
    【解决方案5】:

    我从Rob Vanderwoude's site找到了这段代码:

    @ECHO OFF
    IF [%1]==[] GOTO Syntax
    IF NOT [%2]==[] GOTO Syntax
    ECHO.%1 | FIND "?" >NUL
    IF NOT ERRORLEVEL 1 GOTO Syntax
    IF NOT EXIST %1 GOTO Syntax
    IF NOT "%OS%"=="Windows_NT" GOTO Syntax
    
    SETLOCAL
    SET FileVer=
    FOR /F "tokens=1 delims=[]" %%A IN ('STRINGS %1 ^| FIND /N /V "" ^| FIND /I "FileVersion"') DO SET LineNum=%%A
    SET /A LineNum += 1
    FOR /F "tokens=1* delims=[]" %%A IN ('STRINGS %1 ^| FIND /N /V "" ^| FIND "[%LineNum%]"') DO SET FileVer=%%B
    SET FileVer
    ENDLOCAL
    GOTO:EOF
    
    :Syntax
    ECHO.
    ECHO FileVer.bat,  Version 1.00 for NT 4 / 2000 / XP
    ECHO Display the specified file's version number
    ECHO.
    ECHO Usage:  FILEVER  progfile
    ECHO.
    ECHO Where:  "progfile" is the name of a Windows executable, DLL, or system file
    ECHO.
    ECHO Uses SysInternal's STRINGS.EXE, avalable at http://www.sysinternals.com
    ECHO.
    ECHO Written by Rob van der Woude
    ECHO http://www.robvanderwoude.com
    

    看起来很有趣,因为它使用了来自 SysInternals 的 STRINGS。

    【讨论】:

      【解决方案6】:

      这是我尝试使用WMIC 来获取Skype 目录中所有*.exe*.dll 的文件版本,例如:

      @echo off
      Mode 75,3 & color 9E
      Title Get File Version of any Program from file list using WMIC by Hackoo
      Set "RootFolder=%ProgramFiles%\Skype"
      @for %%a in (%RootFolder%) do set "FolderName=%%~na"
      Set "File_Version_List=%~dp0%FolderName%_File_Version_List.txt"
      Set "ErrorFile=%~dp0%FolderName%_Error.txt
      Set Extensions="*.exe" "*.dll"
      If exist "%ErrorFile%" Del "%ErrorFile%"
      If exist "%File_Version_List%" Del "%File_Version_List%"
      echo(
      echo          Please wait a while ... Process to get file version ...
      set "BuildLineWith=call :BuildLine "
      setlocal enabledelayedexpansion
      CD /D "%RootFolder%"
      @for /f "delims=" %%F in ('Dir /b /s %Extensions%') do (
          set "Version="
          Call :Get_AppName "%%F" AppName
          Call :Add_backSlash "%%F"
          Call :GetVersion !Application! Version
          Call :Remove_backSlash !Application!
          If defined Version (
              (
                  echo !Application!
                  echo !AppName! ==^> !Version!
                  %BuildLineWith%*
              )>> "%File_Version_List%"
          ) else (
              (
                  echo Version is not defined in !Application!
                  %BuildLineWith%#
              )>> "%ErrorFile%"
          )
      )
      If Exist "%ErrorFile%" Start "" "%ErrorFile%"
      If Exist "%File_Version_List%" Start "" /MAX "%File_Version_List%" & Exit
      ::*******************************************************************
      :GetVersion <ApplicationPath> <Version>
      Rem The argument %~1 represente the full path of the application
      Rem without the double quotes
      Rem The argument %2 represente the variable to be set (in our case %2=Version)  
      FOR /F "tokens=2 delims==" %%I IN (
        'wmic datafile where "name='%~1'" get version /format:Textvaluelist 2^>^nul'
      ) DO FOR /F "delims=" %%A IN ("%%I") DO SET "%2=%%A"
      Exit /b
      ::*******************************************************************
      :Add_backSlash <String>
      Rem Subroutine to replace the simple "\" by a double "\\" into a String
      Set "Application=%1"
      Set "String=\"
      Set "NewString=\\"
      Call Set "Application=%%Application:%String%=%NewString%%%"
      Exit /b
      ::*******************************************************************
      :Remove_backSlash <String>
      Rem Subroutine to replace the double "\\" by a simple "\" into a String
      Set "Application=%1"
      Set "String=\\"
      Set "NewString=\"
      Call Set "Application=%%Application:%String%=%NewString%%%"
      Exit /b
      ::*******************************************************************
      :Get_AppName <FullPath> <AppName>
      Rem %1 = FullPath
      Rem %2 = AppName
      for %%i in (%1) do set "%2=%%~nxi"
      exit /b
      ::*******************************************************************
      :BuildLine
      set "LineChar=%1"
      if "%LineChar%"=="" set "LineChar=_"
      for /f "tokens=2 skip=4" %%A in ('mode con: /status') do set "WindowColumns=%%A" & goto :GotColumnCount
      :GotColumnCount
      set "CharLine="
      setlocal EnableDelayedExpansion
      for /L %%A in (1,1,%WindowColumns%) do set "CharLine=!CharLine!!LineChar:~0,1!"
      setlocal DisableDelayedExpansion
      endlocal
      echo %CharLine%
      goto :eof
      ::*******************************************************************
      

      【讨论】:

        【解决方案7】:

        PowerShell 无需外部工具即可轻松读取文件版本,如下所示:

        (Get-Item myFile.exe).VersionInfo.FileVersion
        

        如果您想从批处理文件中读取它,请使用:

        powershell -NoLogo -NoProfile -Command (Get-Item myFile.exe).VersionInfo.FileVersion
        

        并将文件版本保存到变量使用:

        FOR /F "USEBACKQ" %%F IN (`powershell -NoLogo -NoProfile -Command ^(Get-Item "myFile.exe"^).VersionInfo.FileVersion`) DO (SET fileVersion=%%F)
        echo File version: %fileVersion%
        

        我这里走的是真实路径,你也可以绝对定义,比如:C:\myFile.dll

        如果您省略.FileVersion,则会显示有关该文件的更多信息

        【讨论】:

        • 我想在 Windows vista 上默认没有安装 powershell
        猜你喜欢
        • 1970-01-01
        • 2012-10-24
        • 2015-12-11
        • 1970-01-01
        • 2010-11-22
        • 2014-12-12
        • 2010-11-15
        • 2017-07-24
        • 2012-04-06
        相关资源
        最近更新 更多