如何在Windows批处理文件中使用WMIC将DLL或EXE的文件版本转换为变量?

时间:2018-07-24 10:44:27

标签: windows batch-file wmic

我尝试使用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

3 个答案:

答案 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=定义合适的tokensdelims选项来更改此设置。

所有这些项均导致如下代码:

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>。