根据键数动态获取注册表键值

Obtain registry key values dynamically based on number of keys

假设注册表中存在一个位置:

HKEY_CURRENT_USER\Software\ABC\XYZ\

在此位置存在多个值,没有固定数量。但是值名称具有相同的前缀,例如 ABC0ABC1ABC2、...

通常我会使用这个查询来获取每个单独的值:

FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKEY_CURRENT_USER\Software\ABC\XYZ\" /v ABC0`) DO (
    SET Value=%%A
)

这会将 ABC0 的值设置为变量 Value

但我不知道可能存在的值的数量。

有没有什么办法可以获取所有后缀为ABC的值(在上面的位置)存入一个变量或者存入多个变量?

类似于:

值 1 = Value_of_ABC0
值 2 = Value_of_ABC1
等等。

Is there any way to obtain all the values with suffix ABC (in the above location) and store them into a variable or store them in multiple variables?

这个问题可以这样回答:

是的,有一种方法可以获取所有值并将它们存储在一个或多个变量中。

但很可能您也对这个任务的代码感兴趣。

用于将每个值存储在单独的环境变量中的批处理文件。

@echo off
setlocal EnableDelayedExpansion
set "Count=1"
for /F "skip=2 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe query "HKCU\Software\ABC\XYZ"') do (
    set "ValueName=%%A"
    if /I "!ValueName:~0,3!"=="ABC" (
        set "Value!Count!=%%C"
        set /A Count+=1
    )
)
endlocal

将所有值存储在一个环境变量中的批处理文件:

@echo off
setlocal EnableDelayedExpansion
set "Value="
for /F "skip=2 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe query "HKCU\Software\ABC\XYZ"') do (
    set "ValueName=%%A"
    if /I "!ValueName:~0,3!"=="ABC" (
        if not "!Value!"=="" set "Value=!Value!;"
        set "Value=!Value!%%C"
    )
)
endlocal

要了解批处理代码,请打开命令提示符 window,执行以下命令,并阅读每个命令的帮助输出。

  1. for /?
  2. if /?
  3. reg query /?
  4. set /?

参考 Rafael 的评论添加。

reg.exe of Windows 2000 和 Windows XP 不支持变量名上的通配符。自 Windows Vista 以来,仅 reg.exe 支持变量名称中的通配符。

reg.exe 的输出取决于版本和使用的命令。

使用命令

在 Windows XP 上输出
%SystemRoot%\System32\reg.exe query "HKCU\Software\ABC\XYZ"

 
! REG.EXE VERSION 3.0

HKEY_CURRENT_USER\Software\ABC\XYZ
    ABC0        REG_SZ  Hello!
    ABC1        REG_SZ  Okay. Let's go.
    ABC2        REG_SZ  Finished.

输出以空行开始。下一行是版本信息。第三行又是一个空行。第四行是注册表项。然后带有值的行后跟 4 个空格作为缩进,并在值名称、值类型和值字符串之间使用制表符。

使用命令

在 Windows 7 上输出
%SystemRoot%\System32\reg.exe query "HKCU\Software\ABC\XYZ"

 
HKEY_CURRENT_USER\Software\ABC\XYZ
    ABC0    REG_SZ    Hello!
    ABC1    REG_SZ    Okay. Let's go.
    ABC2    REG_SZ    Finished.

第一行又是一个空行。没有版本信息。因此,第二行已经包含注册表项,当然也可以包含 1 个或多个空格。然后带有值的行后面有 4 个空格作为缩进,并且在值名称、值类型和值字符串之间也有 4 个空格。

使用命令

在 Windows 7 上输出
%SystemRoot%\System32\reg.exe query "HKCU\Software\ABC\XYZ" /v ABC*

 
HKEY_CURRENT_USER\Software\ABC\XYZ
    ABC0    REG_SZ    Hello!
    ABC1    REG_SZ    Okay. Let's go.
    ABC2    REG_SZ    Finished.

End of search: 3 match(es) found.

与之前的输出相比,现在多了一个空行和一个包含多个空格的摘要信息。

结论:

可以安全地跳过 reg.exe 的前 2 行输出,就像现在在更新的代码中所做的那样。

但是在 Windows Vista、Windows 7、Windows 8 或 Windows 8.1 上不可能使用像下面这样的简化代码,因为搜索摘要行。

@echo off
setlocal EnableDelayedExpansion
set "Value="
for /F "skip=2 tokens=2*" %%A in ('%SystemRoot%\System32\reg.exe query "HKCU\Software\ABC\XYZ" /v ABC* ') do (
    if not "!Value!"=="" set "Value=!Value!;"
    set "Value=!Value!%%B"
)
endlocal

不过,感谢 Rafael,他的评论让我看到了 reg.exe 版本之间的输出差异,分析它们并在此处记录下来,这对我绝对有帮助,希望也为将来的其他人。