0

this is my first time creating a batch file and I'm relatively new to this coding language. I wish to create a batch file that scans through all DLL files within a folder to retrieve and write the version info into a new text file. The nested for-loop functioned well but I couldn't get the WMIC command to execute, can you help?

Upon double-clicking to run the batch file, this is what I will get:

    Description = Invalid query
    'WMIC DataFile Where "Name='mydirecotry\myfile.dll'" Get Version'
    Node - myPCname

Here are the codes I wrote:

@echo off

SETLOCAL ENABLEDELAYEDEXPANSION 

FOR %%I in (D:\mydirecotry\*.dll*) DO (

    SET Location='WMIC DataFile Where "Name='%%I'" Get Version'
    ECHO !Location!
    
    For /F "Tokens=1* Delims=" %%A In (!Location!) Do (      <---Where i think it went wrong
    
        For /F "Tokens=*" %%B In ("%%~A") Do Set "pver=%%B" 
        
        ECHO %%I - %pver% >> test.txt
    )
)
pause

Thanks in advance.

Listener
  • 13
  • 2
  • The issue is with your WMIC command, more specifically the value of `Name` WMIC requires the backslashes in the names to be escaped with another. This means you're going to have to `Set "dll=%%A"` then use `"Name='!dll:\=\\!'"`. However it may be better if you got rid of all of that code and just used `WMIC /Output:"test.txt" DataFile Where "Drive='D:' And Path='\\mydirectory\\' And Extension='dll'" Get Name, Version`. – Compo Jul 15 '20 at 10:15

2 Answers2

1

As the majority of my earlier comment is already within a supplied answer, I have decided to provide the alternative method I used within that comment, as an answer.

For the task you've laid out in your question, you should be able to have a single line , with no set or for commands, just containing:

@"%__AppDir__%wbem\WMIC.exe" /Output:"test.txt" DataFile Where "Drive='D:' And Path='\\mydirecotry\\' And Extension='dll'" Get Name, Version
Compo
  • 36,585
  • 5
  • 27
  • 39
0

The DLL version information collection task can be done with following batch file:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
(for %%I in ("D:\V4-x64\Exe\Bin\*.dll*") do (
    set "FileName=%%I"
    set "FileName=!FileName:\=\\!"
    for /F "skip=1" %%J In ('%SystemRoot%\System32\wbem\wmic.exe DATAFILE where Name^="!FileName!" GET Version 2^>nul') do if defined FileName set "FileName=" & echo %%I - %%J
)) >test.txt
endlocal

Each backslash in full qualified file name must be escaped with one more backslash. That is a special WMIC requirement on using DATAFILE on which file name must be always specified with full path.

The command line specified within ' is executed by FOR with running in background %ComSpec% /c and the command line in ' appended as additional arguments. So executed is in background with Windows installed to C:\Windows the command line:

C:\Windows\System32\cmd.exe /c C:\Windows\System32\wbem\wmic.exe DATAFILE where Name="D:\\V4-x64\\Exe\\Bin\\FileName.dll" GET Version 2>nul

The equal sign must be escaped with ^ to be interpreted as literal character and not as argument separator as otherwise = would be replaced by a space character before running cmd.exe in background which would make the arguments invalid for wmic.exe.

The redirection operator > must be escaped also with ^ to be interpreted as literal character on parsing the FOR command line before executing FOR at all.

WMIC outputs the data Unicode encoded with UTF-16 Little Endian encoding with byte order mark (BOM). FOR has problems to parse the Unicode output correct as expecting an ASCII/ANSI/OEM character encoding, i.e. one byte per character without null bytes. The byte sequence with the hexadecimal values 0D 00 0A 00 being UTF-16 LE encoded the line ending carriage return + line-feed is interpreted as 0D 0D 0A by FOR (respectively cmd.exe). So there is an erroneous carriage return at end of the real line ending removed by FOR before processing further the remaining string.

For that reason the WMIC output is interpreted with skipping the first line containing just the string Version and so processed is first the second line with the version string by removing leading and trailing spaces.

The full qualified file name of the current DLL file and its version is output with command ECHO. Additionally the environment variable FileName is deleted to make sure that no further line output by WMIC including an empty line interpreted by FOR as a line with just a carriage return results in running once again command ECHO with loop variable J having assigned a carriage return.

The batch file does not work for DLL files with an exclamation mark in file name, but that should not matter here as I have never seen a DLL with ! in file name.

Another solution provided by Compo in a comment is much faster and works also for DLL file names with ! in file name.

@echo off
%SystemRoot%\System32\wbem\wmic.exe DATAFILE Where "Drive='D:' And Path='\\V4-x64\\Exe\\Bin\\' And Extension='dll'" GET Name,Version >"%TEMP%\%~n0.tmp"
%SystemRoot%\System32\more.com +1 "%TEMP%\%~n0.tmp" >test.txt
del "%TEMP%\%~n0.tmp"

WMIC searches itself for *.dll files in the directory D:\V4-x64\Exe\Bin and outputs full name of the DLL file and its version written into a temporary file being UTF-16 LE encoded with BOM. This temporary file is next processed with MORE with skipping the header line and the empty lines at bottom and the output is written into test.txt being a non-Unicode file. The temporary file is deleted finally.

For completeness:

@%SystemRoot%\System32\wbem\wmic.exe DATAFILE Where "Drive='D:' And Path='\\V4-x64\\Exe\\Bin\\' And Extension='dll'" GET Name,Version | %SystemRoot%\System32\more.com +1 >test.txt

This command line produces a non-Unicode encoded text file test.txt on which every line with a DLL file name and version is terminated with two carriage returns and one line-feed and with two empty lines at bottom with just one carriage return plus line-feed. So it is not recommended to use this single line variant.

To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

  • call /? ... explains %~n0 ... file name of argument 0, i.e. the batch file name without file extension.
  • del /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • more /?
  • set /?
  • setlocal /?
  • wmic /?
  • wmic datafile /?
  • wmic datafile get /?

See also single line with multiple commands using Windows batch file for an explanation of the operator & and the Microsoft documentation about Using command redirection operators.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Thank you for your answer. I tried both methods of Compo and yours and they worked equally well. Also, I appreciate the info you provided, it does give a much clearer pic of the batch script after experiencing it first hand. – Listener Jul 16 '20 at 01:42