How do I retrieve the version of a file from a batch file on Windows Vista?

拟墨画扇 提交于 2020-01-19 05:25:28

问题


Binary files have a version embedded in them - easy to display in Windows Explorer.

How can I retrieve that file version, from a batch file?


回答1:


and three ways without external tools

1.WMIC

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

Pay attention to the double slashes of file name.

Ready to use script:

@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 as the WMIC is not installed on home versions of windows here's a way with makecab that will run on every windows machine:

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

example output (it has a string version which is a small addition to wmic method :) ):

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 Using shell.application and hybrid batch\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();

used against 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



回答2:


The file version could be simply read without external tools by PowerShell like this:

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

and if you want to read it from an Batch file use:

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

and to save the file version to a variable use:

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

I've taken a realtive path here, you could also define it absolutely, like: C:\myFile.dll

More information about the file is shown if you omit .FileVersion




回答3:


Check out sigcheck.exe from Sysinternals Suite. This is a command-line utility that shows file version number, timestamp information, and digital signature details.




回答4:


Here is a solution in PowerShell using FileVersionInfo.




回答5:


I think filever is what you need. It can get the file version for multiple items at the same time and locate files (e.g. EXE, DLL) that differ in size or version number.




回答6:


Here is my try using WMIC to get file version of all *.exe and *.dll inside the directory of Skype as example :

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


I've found this code from 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

Looks interesting as it uses STRINGS from SysInternals.



来源:https://stackoverflow.com/questions/1706892/how-do-i-retrieve-the-version-of-a-file-from-a-batch-file-on-windows-vista

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!