在嵌套for循环中执行WMIC命令

问题描述 投票:0回答:2

这是我第一次创建批处理文件,我对这种编码语言相对较新。我希望创建一个批处理文件,扫描文件夹中的所有 DLL 文件,以检索版本信息并将其写入新的文本文件中。嵌套的 for 循环运行良好,但我无法执行 WMIC 命令,你能帮忙吗?

双击运行批处理文件后,这就是我将得到的:

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

这是我写的代码:

@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

提前致谢。

batch-file wmic
2个回答
1
投票

由于我之前的大部分评论已经在提供的答案中,我决定提供我在该评论中使用的替代方法作为答案。

对于您在问题中列出的任务,您应该能够拥有单行,没有

set
for
命令,仅包含:

@"%__AppDir__%wbem\WMIC.exe" /Output:"test.txt" DataFile Where "Drive='D:' And Path='\\mydirecotry\\' And Extension='dll'" Get Name, Version

0
投票

DLL版本信息收集任务可以使用以下批处理文件完成:

@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

完整限定文件名中的每个反斜杠必须再用一个反斜杠转义。这是使用 DATAFILE 的特殊

WMIC
要求,其中文件名必须始终指定完整路径。

'
中指定的命令行由FOR执行,并在后台运行
%ComSpec% /c
,并且
'
中的命令行作为附加参数附加。因此在后台执行,Windows 安装到
C:\Windows
命令行:

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

等号必须用

^
转义才能被解释为文字字符而不是参数分隔符,否则
=
将在后台运行
cmd.exe
之前被空格字符替换,这将使参数对
wmic.exe 无效
.

在执行

FOR
之前,重定向运算符
>
也必须使用 ^ 进行转义,以便在解析 FOR 命令行时被解释为文字字符。

WMIC 输出使用带字节顺序标记 (BOM) 的 UTF-16 Little Endian 编码进行 Unicode 编码的数据。 FOR 在正确解析 Unicode 输出时存在问题,因为需要 ASCII/ANSI/OEM 字符编码,即每个字符一个字节,没有空字节。十六进制值

0D 00 0A 00
为 UTF-16 LE 编码的字节序列,以回车+换行结尾的行被解释为
0D 0D 0A
FOR(分别为
cmd.exe
)。因此,在进一步处理剩余字符串之前,实际行末尾有一个错误的回车符,已被 FOR 删除。

因此,WMIC输出被解释为跳过仅包含字符串

Version
的第一行,因此通过删除前导和尾随空格,首先处理带有版本字符串的第二行。

当前 DLL 文件的完整限定文件名及其版本通过命令 ECHO 输出。此外,环境变量

FileName
被删除,以确保WMIC 不再输出任何行,包括由 FOR 解释为仅包含回车符的行的空行,从而导致使用循环变量再次运行命令 ECHO
J
已指定回车符。

批处理文件不适用于文件名中带有感叹号的 DLL 文件,但这在这里应该不重要,因为我从未见过文件名中带有

!
的 DLL。

Compo在评论中提供的另一个解决方案要快得多,并且也适用于文件名中带有

!
的DLL文件名。

@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 在目录

D:\V4-x64\Exe\Bin
中搜索自身 *.dll 文件,并输出 DLL 文件的全名及其版本,该版本写入使用 BOM 进行 UTF-16 LE 编码的临时文件中。接下来使用 MORE 处理该临时文件,跳过标题行和底部的空行,并将输出写入
test.txt
作为非 Unicode 文件。临时文件终于被删除了。

为了完整性:

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

此命令行生成一个非 Unicode 编码的文本文件

test.txt
,其中包含 DLL 文件名和版本的每一行均以 两个回车符和一个换行符结尾,底部有两个空行,只有一个回车符返回加换行。因此不建议使用这种单行变体。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

  • call /?
    ... 解释
    %~n0
    ... 参数 0 的文件名,即不带文件扩展名的批处理文件名。
  • del /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • more /?
  • set /?
  • setlocal /?
  • wmic /?
  • wmic datafile /?
  • wmic datafile get /?

另请参阅 使用 Windows 批处理文件的单行多个命令,了解运算符

&
的说明以及有关 使用命令重定向运算符的 Microsoft 文档。

© www.soinside.com 2019 - 2024. All rights reserved.