【问题标题】:Put reg query output into a variable将 reg 查询输出放入变量中
【发布时间】:2019-05-03 08:35:48
【问题描述】:

我对 CMD 有点陌生,希望这里有人可以帮助我。

在我的一个旧安装脚本中,我现在需要检查是否安装了 .NET 3.5,然后根据结果安装 3.5 包或继续执行脚本。

现在我在尝试检查脚本中安装的版本时遇到了一些麻烦。

我使用这个 reg 查询来查找已安装的版本:

reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" | Find "3.5"

如果安装了 3.5,则输出一行,否则不输出:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5

现在我的想法是,创建一个变量并用上面看到的输出填充值。

不幸的是:

set DNFound=reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" | Find "3.5"
if not exist %DNFound%
(
 install framework
)

不起作用,因为输出不会保存在变量中。

我进行了一些研究,看到人们使用这种格式的循环来将 reg 查询输出中的单个值获取到变量中(示例代码):

 for /f "tokens=3" %%x in ('reg query HKLM\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile /v EnableFirewall') do set FWSTATUS=%%x

但是,当我尝试执行相同操作时出现语法错误,因为我的 reg 查询中的 | Find "3.5" 部分。

【问题讨论】:

  • 因为涉及到第二个 cmd.exe 实例,您需要使用插入符号 ^| 转义管道符号,您还应该将错误流重定向到 nul 2^>NUL
  • 感谢您的提示,我转义了管道符号并让命令正常工作。这样做的时候发现自己的思维过程是错误的,这里我不检查变量是否存在,而是变量的内容是否存在。所以无论如何我都得走另一条路。
  • 我只是想补充一下,你的问题似乎有点奇怪,事实上 v3.5Windows 7 的操作系统是一体的,这意味着你如果操作系统至少有 10 年的历史,则只需要检查它,(XP 到 Vista/Server 2008 R2)
  • 我们几乎所有的 W10-Workstation 都只安装了 .NET 4.0 及更高版本。
  • 从 Windows 7 开始的每个 Windows 版本,(这意味着您的每个 Windows 10 工作站),已经安装了最低版本的3.5。您的任务无关紧要,因为绝对不需要在其中任何一个上安装它。

标签: .net windows batch-file cmd registry


【解决方案1】:

作为对您问题的补充,因为它可能与未来的用户相关,您应该能够使用类似于此的方法输出所有已安装的版本:

@Echo Off
SetLocal EnableDelayedExpansion
Set "rk=HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP"
Set/A "vi=ri=0"

For /F "Tokens=3*" %%A In ('Reg Query "%rk%" /F v /K') Do If "%%B"=="" (
    If Not "%%~xA"=="" (Set/A "vi+=1"
        For /F "Tokens=2*" %%C In (
            'Reg Query "%rk%\%%~nxA" /V Version 2^>Nul^|Find /V "\"'
        ) Do Set "_v!vi!=%%D"
    ) Else (Set/A "ri+=1"
        For /F "Tokens=2*" %%E In (
            'Reg Query "%rk%\%%~nxA\Full" /V Release 2^>Nul^|Find /V "\"'
        ) Do Set/A "_r!ri!=%%F"))
If %ri% Gtr 0 (Set/A "vi+=1"
    For /F "Tokens=2" %%A In ('FindStr/B "!_r%ri%!" "%~f0"'
    ) Do Set "_v%vi%=%%A")

If %vi% Gtr 0 For /F "Tokens=1* Delims==" %%A In ('Set _v') Do Echo([%%B]

Pause
GoTo :EOF

Rem Later Version Table - do not remove
378389 4.5
378675 4.5.1
378758 4.5.1
379893 4.5.2
393295 4.6
393297 4.6
394254 4.6.1
394271 4.6.1
394802 4.6.2
394806 4.6.2
460798 4.7
460805 4.7
461308 4.7.1
461310 4.7.1
461808 4.7.2
461814 4.7.2
528040 4.8
528049 4.8

当新版本出来时,你只需用相关信息更新底部的内容,这样检测就会保持最新。

【讨论】:

    【解决方案2】:

    我建议你使用errorlevel来判断字符串是否返回成功。

    reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" | Find "3.5"
    if errorlevel 1 install framework
    

    find 返回错误级别 1(不匹配)0 匹配找到。这样你就不需要设置变量了。

    上面可以展开成多个命令:

    reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" | Find "3.5"
    if errorlevel 1 (
        echo Framework not found
        install framework
        echo do something else
    )
    

    至于for循环问题,正如@LotPings在评论中已经提到的,您需要转义管道^|

    for /f "delims=" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" ^| Find "3.5" 2^>nul) do set "var=%%i"
    echo %var%
    

    【讨论】:

    • 有趣的是命令 set DNFound=reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP" | Find "3.5" 确实 NOT 设置 DNFound 并且 always 返回错误级别 1,因为命令 reg 查询永远不会执行(这是不是 bash 或 powershell)
    • 正如 LotPings 已经说过在这里设置变量并没有给我想要的结果。但是,我不再需要该变量,只需删除“set DNFound=”即可获得所需的结果。非常感谢你们俩。如果我知道如何给你们一些 +Rep 我很乐意这样做。
    • @LotPings.. 是的,谢谢你的注意,我忘了删除set 部分.. 直接复制/粘贴失败:) 我修复了它。
    • @NickHH45 是的,这是我这边的一个错误,因为我复制了你的命令,包括集合。我现在修复了它。我们不需要集合,我们只需要来自finderrorlevel 12 的结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 2013-06-29
    • 2020-10-26
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    相关资源
    最近更新 更多