我尝试使用Windows批处理文件获取文件版本。此命令将版本成功打印到控制台。
WMIC DATAFILE WHERE name="Z:\\bin\\My_project.dll" get Version /format:Textvaluelist
但是当我尝试使用以下方法将此输出输出到变量时,Windows命令处理器输出:
Z:\\ bin \\ My_project.dll-无效的别名动词。
此命令行有什么问题?
for /f %%a in ('WMIC DATAFILE WHERE name="Z:\\bin\\My_project.dll" get Version /format:Textvaluelist') do set val=%%a
答案 0 :(得分:2)
这就是我使用WMIC
尝试执行此任务的方式:
For /F "Tokens=1* Delims==" %%A In (
'WMIC DataFile Where "Name='Z:\\bin\\My_project.dll'" Get Version /Value 2^>Nul'
) Do For /F "Tokens=*" %%C In ("%%B") Do Set "val=%%C"
第二个For
循环旨在克服由Unicode WMIC
结果导致的不必要输出。
修改
如果未指定WMIC
,则可以使用批处理文件中的VBScript
:
使用Windows脚本宿主:
<!-- :
@Echo Off
For /F %%A In ('CScript //NoLogo "%~f0?.wsf"') Do Set "val=%%A"
Set val 2>Nul
Pause
Exit /B
-->
<Job><Script Language="VBScript">
WScript.Echo CreateObject("Scripting.FileSystemObject").GetFileVersion("Z:\bin\My_project.dll")
</Script></Job>
或通过mshta.exe
:
@Echo Off
For /F %%A In ('
MsHTA VBScript:Execute("Set o=CreateObject(""Scripting.FileSystemObject""):o.GetStandardStream(1).Write(o.GetFileVersion(""Z:\bin\My_project.dll"")):Close"^)
') Do Set "val=%%A"
Set val 2>Nul
Pause
答案 1 :(得分:1)
问题是您的where
子句中的等号,cmd
将其视为标准令牌分隔符,就像 SPACE , TAB一样,,
,;
,垂直制表符(代码0x0B
),换页(代码0x0C
)和不间断空格(代码{ {1}}。
0xFF
命令在单独的for /F
实例中执行要解析的命令,但在此之前,标准令牌分隔符的每个序列都被单个 SPACE 替换。 。因此cmd
也被替换了,这留下了一些奇怪的语法。
要从字面上保留=
符号,您需要像=
一样对其进行转义。另一种方法是更改引号样式,以便通过声明^=
在=
之间出现""
。
但是,这仍然不能提供预期的结果,因为wmic DataFile where "Name='Z:\\bin\\My_project.dll'" get Version
返回Unicode输出,这留下了一些令人不安的转换伪像,例如孤立的回车符。可以通过嵌套另一个wmic
循环来避免这种情况。
此外,由于您选择了输出格式,因此您还将获得一个for /F
前缀,这可能不是您想要包含的前缀。可以通过为Version=
定义合适的tokens
和delims
选项来更改此设置。
所有这些项均导致如下代码:
for /F
这会从返回的版本中删除所有前导for /F "usebackq delims=" %%a in (`
wmic DataFile where "Name='Z:\\bin\\My_project.dll'" get Version /VALUE
`) do for /F "tokens=1* delims==" %%b in ("%%a") do set "val=%%c"
符号,如果有的话。
答案 2 :(得分:1)
获取DLL版本的最简单解决方案是在批处理文件中使用以下命令行:
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"
批处理文件中的命令行也可能略有不同:
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 在以cmd /C
开头的单独命令过程中,在圆括号中运行该命令,并捕获输出到该命令过程 STDOUT 的所有行。因此,必须考虑当前正在处理批处理文件的cmd.exe
实例如何解析整个命令行以及 FOR 如何处理圆括号中的参数字符串。
当Windows命令处理器在执行 FOR 之前解析命令行时,必须使用>
对双引号字符串之外的^
这样的重定向运算符进行转义,以使其首先被解释为文字字符。 strong>。
FOR 将双引号引起来的等号=
解释为参数分隔符,例如空格或逗号,在命令提示符窗口中运行时可以看到例如:
for %I in ("space ' ' and comma ',' and equal sign '='" space,comma=equal_sign) do @echo %I
此命令行输出:
"space ' ' and comma ',' and equal sign '='"
space
comma
equal_sign
因此,双引号之外的=
也必须用^
进行转义,才能首先解释为文字字符。
第二种解决方案使用替代的 WMIC 语法将等号嵌入双引号字符串中,并使用不同的 FOR 语法使用反引号来使用{{ 1}}在命令行中,由 FOR 执行。
WMIC 输出,带有选项'
或/VALUE
,例如:
/FORMAT:Textvaluelist
因此, WMIC 输出由两个空行组成,查询信息
Version=1.0.0.11
带有等号和版本值,以及另外两个空行。
问题是 WMIC 始终使用带有字节顺序标记(BOM)的UTF-16 Little Endian字符编码输出总是查询的数据,并且 FOR 在处理此错误Unicode输出正确。 FOR 将最后两行UTF-16编码的空行解释为带有回车符+回车符+换行符的一行。有关此 FOR 错误的详细信息,请参见:
此错误可通过使用选项Version
来获得 WMIC 以格式/VALUE
的一行并使用 FOR 输出的所需信息来解决。 strong>选项Version=value
。仅捕获的带有tokens=2 delims==
的行具有两个由等号分隔的字符串,因此,仅在该行上用等号后的值执行命令 SET 。带有版本信息的两行之后的空行,被 FOR 误认为只有一行回车,不会导致执行命令 SET ,因为没有第二个字符串可以将其分配给循环变量Version=value
。
此代码期望版本字符串本身不包含一个或多个I
,对于DLL版本,情况总是如此。
注意:分别更改环境变量=
的值,如果发生任何错误(例如根本找不到DLL文件),则仍未定义该环境变量。通过使用val
(使用转义2>nul
)从 STDERR 重定向到设备 NUL,可以抑制 WMIC 输出的错误消息。 strong>。