我正在尝试在许多服务器上查询已安装应用程序的注册表值。我可以硬编码服务器,并有很多重复,它似乎工作。但有时服务器列表可能会发生变化,我想采用更合理的模块化方法。
所以我可以提供一个包含服务器名称列表的测试文件,然后查询所有这些服务器的注册表值,并将它们输出到日志文件中。
我认为问题肯定在于我的循环/变量存储。不确定到底发生了什么,但似乎一旦我得到一组注册表值,就会为每个服务器输出这些值,而不管它们各自的注册表值。
对这种脚本没有太多经验,所以我通过反复尝试将它们混合在一起,下面是我到目前为止所做的。请指出我所犯的任何可怕的语法错误。
基本上,这是为每台服务器安装一个McAfee扫描引擎版本。来自McAfee控制台本身的报告并不总是可靠的,我想检查内容是否已成功下载到每个服务器。
创建完整引擎版本需要两个注册表值,因此我需要同时提取这两个值,然后将它们组合成一个字符串。
目前我确实得到了一个看起来正确的输出,但它并不代表实际安装到每个服务器的内容。就像一个值被拾取然后被复制。
另外请注意,这只在命令行中执行时才有效。并且运行前1-2次,没有值被提升。感觉我离解决方案很远。
SET LOGFILE=C:\LogFile.log
For /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query \\%%i\HKLM\SOFTWARE\McAfee\AVEngine /v EngineVersion32Major ^| find /i "EngineVersion32Major"') do set /a major=%%a
for /f "tokens=3" %%b in ('reg query \\%%i\HKLM\SOFTWARE\McAfee\AVEngine /v EngineVersion32Minor ^| find /i "EngineVersion32Minor"') do set /a minor=%%b
echo %%i: %major%.%minor% >> %LOGFILE%
)
期望这样的输出:
server1 : 5900.5647
server2 : 6000.4589
server3 : 5900.5647
server4 : 5900.5647
欢呼您提供任何帮助。
答案 0 :(得分:2)
它与for
语法无关,但cmd
如何解析脚本。见How does the Windows Command Interpreter (CMD.EXE) parse scripts?
当cmd
解析一个块(parens中的任何内容)时,将其作为一行进行处理。因此,它将任何%var%
扩展为其实际内容。在退出块之前,不会考虑对其所做的更改。要检索块中的新内容,必须启用delayed expansion
,这会强制解析器在每次迭代时对其进行评估。此外,语法必须从%var%
更改为!var!
此处,还从/a
命令中移除了set
开关,因为您没有进行计算,并且您可能会得到您不会期望的结果(想象一下等于{的次要版本{1}}将被视为八进制(无效)并将破坏脚本)。另外,请注意用引号(0080
)括起的var name和var内容,以避免不需要的尾随/前导空格。
此外,我认为您不需要set "minor=%%b"
部分,因为名为^| find /i "EngineVersion32Major
的密钥可能只会满足您的要求。再次,将数据括在引号中(永远不知道何时可能出现空格)。您也可以按EngineVersion32Major
更改"tokens=3"
,以避免处理标题"skip=1 tokens=3"
回音。
因此
reg
此外,无论是否启用延迟扩展,这都适用于块(注意双百分号)
@echo off
SetLocal EnableDelayedExpansion
SET LOGFILE=C:\LogFile.log
for /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Major"') do set "major=%%a"
for /f "tokens=3" %%b in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Minor"') do set "minor=%%b"
echo %%i: !major!.!minor!>>%LOGFILE%
)
EndLocal
另一个问题是,无论何时在块内使用重定向,系统都会打开并关闭文件(或流)。
但是
call echo %%i: %%major%%.%%minor%%>>%LOGFILE%
处理块中的所有命令,因此文件只打开和关闭一次。这可以提高性能,特别是对于大文件。
BTW,
@echo off
SetLocal EnableDelayedExpansion
SET LOGFILE=C:\LogFile.log
>>"%LOGFILE%" (
for /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Major"') do set "major=%%a"
for /f "tokens=3" %%b in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Minor"') do set "minor=%%b"
echo %%i: !major!.!minor!
)
)
EndLocal
与
相同>>"%LOGFILE%" (
...
...
)
答案 1 :(得分:0)
请使用search
工具在delayed expansion
上找到许多SO文章。
您的案例中的简单方法是使用
call echo %%i: %%major%%.%%minor%% >> %LOGFILE%