使用批处理文件读取包含空格的注册表值

8
我有一个批处理文件,用于读取注册表值。然而我读取的条目包含空格,当设置变量时似乎只捕获第一个空格字符之前的所有内容。
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\My Entry"
set VALUE_NAME=Home

FOR /F "usebackq skip=2 tokens=1-3" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
    set ValueName=%%A
    set ValueType=%%B
    set Home=%%C
)

if defined ValueName (
    @echo Home = %Home%
) else (
    @echo %KEY_NAME%\%VALUE_NAME% not found.
)

主目录注册表实际包含此字符串:"C:\Program Files (x86)\Dir1\Dir2",而批处理文件仅捕获了这个:"C:\Program"

有人有修复此问题的想法吗?

谢谢。


REG QUERY %KEY_NAME% /v %VALUE_NAME% 的输出是什么? - user2033427
输出正在显示注册表名称、类型和数据(现在是完整的,即包括整个字符串 :-))。我该如何将其中的数据部分存储在变量中?谢谢! - Yos
3个回答

10

这个问题是由于字符串包含空格,且字符串的第二部分(如果有更多的空格,则可能还有更多的部分)被视为另一个标记(在4、5等中)。要解决此问题,请像这样将行的其余部分以星号传递给 %%C:

FOR /F "usebackq skip=2 tokens=1,2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
    set ValueName=%%A
    set ValueType=%%B
    set Home=%%C
)
< p >星号 (*) 表示将该行的其余部分传递到下一个变量中(包括所有空格)。< /p >

啊,我明白你的意思了。我的担心是路径可能会有很多空格,因此增加令牌等是不可能确定的?非常感谢。我已经修改了我的代码,看起来效果很好。干杯! - Yos
在我的测试中,2* 会为每个空格分隔的元素创建变量。因此,返回带有空格路径的 reg query 将产生 %c%d。例如:FOR /F "tokens=2,3* skip=2" %%L IN ( 'reg query "HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDKTools" /v InstallationFolder' ) DO echo %%M 返回 C:\Program - Craig Ringer

4
@ECHO OFF
SETLOCAL
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\My Entry"
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Space Sciences Laboratory, U.C. Berkeley\BOINC Setup"
set VALUE_NAME=migrationdir

FOR /F "usebackq skip=2 tokens=1,2*" %%A IN (
 `REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
    set "ValueName=%%A"
    set "ValueType=%%B"
    set Home="%%C"
)

IF DEFINED home SET home=%home:"=%
if defined Home echo Home = %Home%
if NOT defined Home echo %KEY_NAME%\%VALUE_NAME% not found.

由于我没有...\My Entry作为关键字,所以我替换了一个我有的关键字。

第一项 - 由于所需数据包含空格,并且空格是默认分隔符,因此需要使用1,2*作为标记 - 第一个、第二个和剩余行。

下一个小困难是数据项还包含),它被解释为FOR/f的闭括号,从而产生错误 - 在您的情况下,这里不期望\Dir1\Dir2

克服这个问题的一种方法是引用然后剥离分配给home的值。

但是,再次出现在home中的右括号会终止IF语句的TRUE部分。

通过开启对分配给HOME的值的存在/不存在来解决这个问题。显然,对于Valuename也可以说相同的话,虽然这里存在隐藏的失败。

如果未找到请求的注册表项,则不执行FOR/f中的SET,因此三个变量的值不会从执行FOR/f之前的任何值更改。因此,如果在for/f之前,home(或者如果您选择使用该值,则为valuename)的值为someexistingvalue,则可能会呈现意外结果。

(顺便说一句 - 在IN子句的任何一个或两个括号处中断for/f是合法且更整洁的方式)


哇,多么棒且深入的回答啊!我正在使用user2033427所描述的解决方案,它似乎非常有效。然而,您给了我一些值得思考的东西,并且解释得很好。诀窍是在tokens命令中添加*。谢谢大家! - Yos
嗨,在玩弄这两个示例之后,似乎这个允许我检查 home 变量是否已赋值,上面的解决方案在尝试检查 home 是否已定义时会抛出错误,正如你指出的那样。谢谢,现在我使用了这段代码,因为它似乎运行得很好。除了我刚提到的那个问题外,上面的代码也可以工作!:-) - Yos

0

我使用delims=:来解决目录中未知数量的空格问题。

这种解决方案仅适用于带有磁盘字母的目录或文件路径的值,因此这不是通用解决方案...

ECHO OFF
SETLOCAL ENABLEEXTENSIONS

FOR /F "tokens=1,2* skip=2 delims=:" %%a in ('REG QUERY "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Administrative Tools" 2^>nul') DO (SET "regA=%%a" & SET "regB=%%b")
SET usrDeskPath=%regA:~-1%:%regB%

ECHO.
ECHO %usrDeskPath%

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接