在嵌套 for 循环中执行 WMIC 命令
Execute WMIC command in nested for-loop
这是我第一次创建批处理文件,我对这种编码语言还比较陌生。我希望创建一个批处理文件来扫描文件夹中的所有 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
提前致谢。
DLL 版本信息 collection 任务可以使用以下批处理文件完成:
@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
和[=15中的命令行=] 作为附加参数附加。所以在后台执行,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
等号必须用 ^
转义才能被解释为文字字符而不是参数分隔符,否则 =
将被 [=157] 之前的 space 字符替换=] cmd.exe
在后台,这将使参数对 wmic.exe
.
无效
重定向运算符 >
也必须使用 ^
进行转义,以便在执行 [=83] 之前解析 FOR 命令行时被解释为文字字符=]完全。
WMIC 输出使用带字节顺序标记 (BOM) 的 UTF-16 Little Endian 编码的 Unicode 数据。 FOR 无法正确解析 Unicode 输出,正如预期的 ASCII/ANSI/OEM 字符编码,即每个字符一个字节,没有空字节。十六进制值 0D 00 0A 00
的字节序列是 UTF-16 LE 编码的行结尾回车符 return + line-feed 被 FOR[= 解释为 0D 0D 0A
112=](分别为cmd.exe
)。因此,在进一步处理剩余字符串之前,FOR 删除的实际行末尾有一个错误的回车 return。
出于这个原因,WMIC 输出被解释为跳过仅包含字符串 Version
的第一行,因此首先处理带有版本字符串的第二行删除前导和尾随 spaces.
当前 DLL 文件的完整限定文件名及其版本通过命令 ECHO 输出。此外,环境变量 FileName
被删除,以确保 WMIC 不再输出任何行,包括被 FOR 解释为只有一个回车 return 的行导致 运行 再次命令 ECHO 循环变量 J
分配了一个回车 return.
批处理文件不适用于文件名中带有感叹号的 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 文件的全名及其写入临时文件的版本为 UTF- 16 LE 用 BOM 编码。这个临时文件接下来用 MORE 处理,跳过 header 行和底部的空行,输出被写入 test.txt
作为 non-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
此命令行生成一个 non-Unicode 编码的文本文件 test.txt
,其中包含 DLL 文件名和版本的每一行都以 两个 回车符 returns 和一个 line-feed 并且底部有两个空行,只有一个马车 return 加上 line-feed。所以不建议使用这种单行变体。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
... 解释 %~n0
... 参数 0 的文件名,即不带文件扩展名的批处理文件名。
del /?
echo /?
endlocal /?
for /?
if /?
more /?
set /?
setlocal /?
wmic /?
wmic datafile /?
wmic datafile get /?
另见 single line with multiple commands using Windows batch file for an explanation of the operator &
and the Microsoft documentation about Using command redirection operators。
由于我之前的大部分评论已经在提供的答案中,我决定提供我在该评论中使用的替代方法作为答案。
对于您在问题中提出的任务,您应该能够有一行 batch-file,没有 set
或 for
命令,仅包含:
@"%__AppDir__%wbem\WMIC.exe" /Output:"test.txt" DataFile Where "Drive='D:' And Path='\mydirecotry\' And Extension='dll'" Get Name, Version
这是我第一次创建批处理文件,我对这种编码语言还比较陌生。我希望创建一个批处理文件来扫描文件夹中的所有 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
提前致谢。
DLL 版本信息 collection 任务可以使用以下批处理文件完成:
@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
和[=15中的命令行=] 作为附加参数附加。所以在后台执行,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
等号必须用 ^
转义才能被解释为文字字符而不是参数分隔符,否则 =
将被 [=157] 之前的 space 字符替换=] cmd.exe
在后台,这将使参数对 wmic.exe
.
重定向运算符 >
也必须使用 ^
进行转义,以便在执行 [=83] 之前解析 FOR 命令行时被解释为文字字符=]完全。
WMIC 输出使用带字节顺序标记 (BOM) 的 UTF-16 Little Endian 编码的 Unicode 数据。 FOR 无法正确解析 Unicode 输出,正如预期的 ASCII/ANSI/OEM 字符编码,即每个字符一个字节,没有空字节。十六进制值 0D 00 0A 00
的字节序列是 UTF-16 LE 编码的行结尾回车符 return + line-feed 被 FOR[= 解释为 0D 0D 0A
112=](分别为cmd.exe
)。因此,在进一步处理剩余字符串之前,FOR 删除的实际行末尾有一个错误的回车 return。
出于这个原因,WMIC 输出被解释为跳过仅包含字符串 Version
的第一行,因此首先处理带有版本字符串的第二行删除前导和尾随 spaces.
当前 DLL 文件的完整限定文件名及其版本通过命令 ECHO 输出。此外,环境变量 FileName
被删除,以确保 WMIC 不再输出任何行,包括被 FOR 解释为只有一个回车 return 的行导致 运行 再次命令 ECHO 循环变量 J
分配了一个回车 return.
批处理文件不适用于文件名中带有感叹号的 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 文件的全名及其写入临时文件的版本为 UTF- 16 LE 用 BOM 编码。这个临时文件接下来用 MORE 处理,跳过 header 行和底部的空行,输出被写入 test.txt
作为 non-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
此命令行生成一个 non-Unicode 编码的文本文件 test.txt
,其中包含 DLL 文件名和版本的每一行都以 两个 回车符 returns 和一个 line-feed 并且底部有两个空行,只有一个马车 return 加上 line-feed。所以不建议使用这种单行变体。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
... 解释%~n0
... 参数 0 的文件名,即不带文件扩展名的批处理文件名。del /?
echo /?
endlocal /?
for /?
if /?
more /?
set /?
setlocal /?
wmic /?
wmic datafile /?
wmic datafile get /?
另见 single line with multiple commands using Windows batch file for an explanation of the operator &
and the Microsoft documentation about Using command redirection operators。
由于我之前的大部分评论已经在提供的答案中,我决定提供我在该评论中使用的替代方法作为答案。
对于您在问题中提出的任务,您应该能够有一行 batch-file,没有 set
或 for
命令,仅包含:
@"%__AppDir__%wbem\WMIC.exe" /Output:"test.txt" DataFile Where "Drive='D:' And Path='\mydirecotry\' And Extension='dll'" Get Name, Version