How can I compare the versions of two executables from the command line?

I have two executables (file1.exe and file2.exe).

Both are the "same" file, but one is a newer version from the vendor than the other. When I open up the properties for one of them, I get the following under the Details tab:

enter image description here

In batch, I'd like to compare the two file versions and do something if the versions are different ("if this, then that" type of scenario).

I've searched high and low, but I can't seem to find a method of looking at the "File Version" attribute in batch. Is there any means of accomplishing this?

Please note that this is not intended to be a "write a script for me" question. The intent is for a more general overview or description of the answer, at which point, the details should be able to come much more easily.


Solution 1:

Sigcheck - Sysinternals Suite

sigcheck -a -q %windir%\system32\mstsc.exe

- if need add MD5, SHA1, PESHA1, SHA256

    sigcheck -a -q -h %windir%\system32\mstsc.exe

- test version, and run command:

    sigcheck -a -q %windir%\system32\mstsc.exe | find "Prod version:" | find "6.0.6001.18564" && Echo "RDP 6.0.6001.18564"

filever - Support tools:

Windows XP Service Pack 2 Support Tools or

Windows Server 2003 Service Pack 2 32-bit Support Tools

filever /V %windir%\system32\mstsc.exe

var 2:

  • filever /V %windir%\system32\mstsc.exe | findstr "FileDesc Version"
    
  • filever /V %windir%\system32\mstsc.exe | findstr "ProductVersion" | find "6.0.6001.18564" && Echo "RDP 6.0.6001.18564"
    
  • filever /V %windir%\system32\mstsc.exe | findstr "ProductVersion" | find "6.0.6001.18564" || Echo "NOT 6.0.6001.18564"
    

wmic:

wmic datafile where "name='C:\\<windows dir>\\system32\\mstsc.exe'" get version

Powershell:

FileDescription:

powershell (gi %windir%\system32\mstsc.exe).versioninfo.FileDescription

version:

powershell (gi %windir%\system32\mstsc.exe).versioninfo ^|Ft -Au

script version compare:

$VerArr = [version]"8.2.6001.18564", [version]"6.0.6001.18564"
[version]$v1="8.2.6001.18564"
[version]$v2="6.0.6001.18564"
[version]$v3=(gi $env:windir\system32\mstsc.exe).versioninfo.ProductVersion
$v3
$v3 -ge $v1
$v3 -ge $v2
If ($VerArr -contains $v3)
   {
   echo 'Run version list block'
   }

output:

Major  Minor  Build  Revision
-----  -----  -----  --------
6      0      6001   18564
False
True
Run version list block

WSH:

cscript //Nologo vers01.vbs

vers01.vbs:

WScript.Echo CreateObject("Scripting.FileSystemObject").GetFileVersion(CreateObject("WScript.Shell").Environment("Process")("WINDIR") & "\system32\mstsc.exe")

JScript:

cscript //Nologo vers01.js

vers01.js:

WScript.Echo(new ActiveXObject("Scripting.FileSystemObject").GetFileVersion(new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings("%windir%")+"//system32//mstsc.exe"));

python, pefile:

pefile modyle install: Unzip, run python setup.py install

import pefile, os

pe = pefile.PE(os.path.join(os.environ['WINDIR'],'system32\mstsc.exe'))
ProductVersion = pe.FileInfo[0].StringTable[0].entries['ProductVersion']
print ProductVersion

PHP:

php vers01.php

php.ini (%windir%):

extension_dir = C:\php\ext\

[COM_DOT_NET]
extension=php_com_dotnet.dll

vers01.php:

<?php
$path = getenv('SystemRoot').'\\system32\\mstsc.exe';
$fso = new COM("Scripting.FileSystemObject");
echo $fso->GetFileVersion($path);
?>

Perl:

Install Win32::File::VersionInfo module: cpan Win32::File::VersionInfo

use Win32::File::VersionInfo;

  $fn=$ENV{windir} . "\\system32\\mstsc.exe";
  $fl=GetFileVersionInfo($fn);
  if($fl){print $fl->{FileVersion},"\n";}

Solution 2:

@STTR' answer is fine, except it does not provide a way to namely compare versions in batch, as this may be also the problem, for example, when comparing 10.0.10049 with 6.3.9600.

If you'll do it with plain IF %ver1% GTR %ver%, you'll get string comparison, and 6.3.9600 will appear bigger than 10.0.10049.

I know you've told it's not "write for me", but this is case when it's easier to write code than explain in plain English (and the code is self-explanatory).

From https://superuser.com/a/363308/131936 I've found how to read file version using wmic, which is shipped with bare windows.

compareVersion.cmd

(
SETLOCAL
ECHO Usage: %0 <file> [<MinVer>]
ECHO If second argument provided, returns error level 1 if version of file is less than required
ECHO Otherwise, sets %%filever%% variable to file version No.

rem https://superuser.com/a/363308/131936
SET "fileNameForWMIC=%~1"
)
SET fileNameForWMIC=%fileNameForWMIC:\=\\%
FOR /F "usebackq skip=1" %%I IN (`wmic datafile where Name^="%fileNameForWMIC%" get Version`) DO (
    SET filever=%%~I
    GOTO :break
)
:break
(
IF "%~2"=="" (
    ENDLOCAL
    SET "filever=%filever%"
    EXIT /B
)
FOR /F "delims=. tokens=1,2,3,4" %%I IN ("%filever%") DO (
    SET fileverSub1=%%I
    SET fileverSub2=%%J
    SET fileverSub3=%%K
    SET fileverSub4=%%L
)
FOR /F "delims=. tokens=1,2,3,4" %%I IN ("%~2") DO (
    SET chkSub1=%%I
    SET chkSub2=%%J
    SET chkSub3=%%K
    SET chkSub4=%%L
)
IF NOT DEFINED fileverSub2 SET fileverSub2=0
IF NOT DEFINED fileverSub3 SET fileverSub3=0
IF NOT DEFINED fileverSub4 SET fileverSub4=0
IF NOT DEFINED chkSub2 SET chkSub2=0
IF NOT DEFINED chkSub3 SET chkSub3=0
IF NOT DEFINED chkSub4 SET chkSub4=0
)
(
ENDLOCAL
IF %chkSub1% GTR %fileverSub1% EXIT /B 1
IF %chkSub2% GTR %fileverSub2% EXIT /B 1
IF %chkSub3% GTR %fileverSub3% EXIT /B 1
IF %chkSub4% GTR %fileverSub4% EXIT /B 1
EXIT /B 0
)

How to use this regarding you your question:

first, read one file version:

CALL compareVersion.cmd file1.exe
SET file1ver=%filever%

then compare it with other file(s):

CALL compareVersion.cmd file2.exe %file1ver%

IF ERRORLEVEL 1 (
    … do this when file2 is lower version than file1…
) ELSE (
    … do this when file2 is higher or equal to version of file1…
)

also, you can hardcode version, if you want:

CALL compareVersion.cmd file2.exe 1.2.3.4 || (ECHO Min required version 1.2.3.4 not provided & EXIT /B)

P.S. Here is my script to read/check windows version, built on similar principle.

Solution 3:

Not exactly for version checking, but you can calculate and compare the MD5 or SHA1 checksum of two files and then compare if they're the same. If the checksum strings are equal, the two files are exactly same (hence the same version), else different.

You can use the FCIV tool in command line to calculate checksum.