The simplest solution to get version of a DLL is using this command line in a batch file:
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe DATAFILE WHERE name^="Z:\\bin\\My_project.dll" get Version /VALUE 2^>nul') do set "val=%%I"
Also possible is this slightly different command line in a batch file:
for /F "usebackq tokens=2 delims==" %%I in (`%SystemRoot%\System32\wbem\wmic.exe DATAFILE WHERE "name='Z:\\bin\\My_project.dll'" GET Version /VALUE 2^>nul`) do set "val=%%I"
FOR runs the command in the round brackets using a separate command process started with %ComSpec% /c
in the background and captures all lines output to STDOUT of this command process. For that reason it must be taken into account how cmd.exe
instance currently processing the batch file parses the entire command line and how FOR processes the argument strings within the round brackets.
A redirection operator like >
outside a double quoted string must be escaped with ^
to get it interpreted first as literal character when Windows command processor parses the command line before executing FOR.
And an equal sign =
outside a double quoted string is interpreted by FOR as an argument separator like a space or a comma as it can be seen on running in a command prompt window for example:
for %I in ("space ' ' and comma ',' and equal sign '='" space,comma=equal_sign) do @echo %I
This command line outputs:
"space ' ' and comma ',' and equal sign '='"
space
comma
equal_sign
For that reason also =
outside a double quoted string must be escaped with ^
to be interpreted first as literal character.
The second solution uses an alternate WMIC syntax to embed the equal sign in a double quoted string and a different FOR syntax using back quotes to be able to use '
in command line to execute by FOR.
WMIC outputs with option /VALUE
or /FORMAT:Textvaluelist
for example:
Version=1.0.0.11
So the WMIC output consists of two empty lines, the queried information Version
with an equal sign and the version value, and two more empty lines.
The problem is that WMIC outputs always the queried data using UTF-16 Little Endian character encoding with byte order mark (BOM) and FOR has a bug on processing this Unicode output correct. FOR interprets a byte sequence with the hexadecimal values 0D 00 0A 00
being UTF-16 LE encoded the line ending carriage return + line-feed as 0D 0D 0A
. So there is an erroneous carriage return at end of the real line ending removed by FOR before processing further the remaining string.
For details about this FOR bug see for example:
This bug is worked around here partly by using option /VALUE
to get the wanted information output by WMIC on one line in format Version=value
and using FOR options tokens=2 delims==
. Only the captured line with Version=value
has two strings separated by an equal sign and so the command SET is executed only on this line with the value after the equal sign. The two empty lines before and the two empty lines after line with version information, wrong interpreted by FOR as lines with just a carriage return, do not result in executing command SET as there is no second string which could be assigned to loop variable I
.
It is expected by this code that the version string does not contain itself one or more =
which should be always the case for version of a DLL.
Note 1: The value of environment variable val
is unmodified respectively this environment variable is still not defined if any error occurs like the DLL file is not found at all. The error message output by WMIC is suppressed by redirecting it with 2>nul
(with escaping >
) from STDERR to device NUL.
Note 2: The version string assigned to the environment variable val
has as last character the erroneous carriage return. That must be taken into account on further processing the string value of val
. The solutions of Compo and aschipfl using two FOR loops as posted are better because the environment variable val
is defined with the version string of the DLL without the erroneous carriage return.