![](/img/trans.png)
[英]How to get a path variable in a text file by using FOR in a Windows batch file?
[英]How to get file version of a DLL or EXE to a variable using WMIC in a Windows batch file?
我尝试使用 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
这就是我使用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
问题在于where
子句中的等号,它被cmd
视为标准标记分隔符,就像SPACE , TAB , ,
, ;
、垂直制表符(代码0x0B
)、换页(代码0x0C
)和不间断空格(代码0xFF
)。
for /F
命令在单独的cmd
实例中执行要解析的命令,但在此之前,每个标准标记分隔符序列都被单个SPACE替换。 所以=
也被替换了,这留下了一些奇怪的语法。
要真正保留=
符号,您需要像^=
一样将其转义。 另一种方法是更改引用样式,以便=
出现在""
之间,方法是声明wmic DataFile where "Name='Z:\\\\bin\\\\My_project.dll'" get Version
。
但这仍然没有提供预期的结果,因为wmic
返回 Unicode 输出,这留下了一些令人不安的转换人工制品,如孤立的回车字符。 这可以通过嵌套另一个for /F
循环来避免。
此外,由于您选择的输出格式,您还将获得Version=
前缀,这可能不是您想要包含的内容。 这可以通过for /F
定义合适的tokens
和delims
选项来改变。
所有这些项目都会导致如下代码:
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"
这将从返回的版本中删除任何前导=
-signs,如果有的话。
获取 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使用以%ComSpec% /c
在后台启动的单独命令进程运行圆括号中的命令,并将所有行输出捕获到此命令进程的STDOUT 。 因此,必须考虑当前处理批处理文件的cmd.exe
实例如何解析整个命令行以及FOR如何处理圆括号内的参数字符串。
当 Windows 命令处理器在执行FOR之前解析命令行时,必须使用^
转义双引号字符串外的像>
这样的重定向运算符,以使其首先被解释为文字字符。
并且双引号字符串外的等号=
被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语法,以便能够在命令行中使用'
以通过FOR执行。
带有选项/VALUE
或/FORMAT:Textvaluelist
WMIC输出,例如:
Version=1.0.0.11
所以WMIC输出由两个空行组成,查询信息Version
带有等号和版本值,另外两个空行。
问题是WMIC总是使用带有字节顺序标记 (BOM) 的 UTF-16 Little Endian 字符编码输出查询数据,并且FOR在正确处理此 Unicode 输出时存在错误。 FOR将十六进制值0D 00 0A 00
的字节序列解释为 UTF-16 LE 将行尾回车 + 换行编码为0D 0D 0A
。 因此,在进一步处理剩余字符串之前,在由FOR删除的实行结尾处有一个错误的回车符。
有关此FOR错误的详细信息,请参见例如:
此错误是在这里工作部分是通过使用选项/VALUE
来获得想要的信息输出由WMIC在格式一行Version=value
对期权和使用tokens=2 delims==
。 只有Version=value
的捕获行有两个由等号分隔的字符串,因此命令SET仅在等号后的值的这一行上执行。 带有版本信息的前两个空行和后两个空行被FOR错误地解释为只有回车的行,不会导致执行命令SET,因为没有第二个字符串可以分配给循环变量I
。
这段代码期望版本字符串本身不包含一个或多个=
,对于 DLL 的版本来说应该总是如此。
注 1:环境变量val
值未修改,如果出现任何错误,如根本找不到 DLL 文件,则该环境变量仍未定义。 WMIC输出的错误消息通过使用2>nul
(带有转义>
)从STDERR重定向到设备NUL来抑制。
注 2:分配给环境变量val
的版本字符串的最后一个字符是错误的回车符。 在进一步处理val
的字符串值时必须考虑到这一点。 的解决方案康波和aschipfl使用两个for循环张贴更好,因为环境变量val
与DLL的版本字符串没有错误回车确定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.