75

I need to use a REG QUERY command to view the value of a key and set the result into a variable with this command:

FOR /F "tokens=2* delims=    " %%A IN ('REG QUERY "KeyName" /v ValueName') DO SET Variable=%%B

But if the key doesnt exists i get an error shown in the console. I need to hide this error! I tried putting a 2>nul after the command to stop the stderr, but this works if i only call the command:

REG QUERY "KeyName" /v ValueName 2>nul

If i put it into the FOR command like this:

FOR /F "tokens=2* delims=    " %%A IN ('REG QUERY "KeyName" /v ValueName') DO SET Variable=%%B 2>nul

The error is shown. So does anyone know how to hide the error? Or maybe another command too see if a key exists or not?

Thanks

PS: I'm using Windows XP

0

18 Answers 18

71

This works for me:

@echo OFF

setlocal ENABLEEXTENSIONS
set KEY_NAME="HKEY_CURRENT_USER\Software\Microsoft\Command Processor"
set VALUE_NAME=DefaultColor

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

if defined ValueName (
    @echo Value Name = %ValueName%
    @echo Value Type = %ValueType%
    @echo Value Value = %ValueValue%
) else (
    @echo %KEY_NAME%\%VALUE_NAME% not found.
)

usebackq is needed since the command to REG QUERY uses double quotes.

skip=4 ignores all the output except for the line that has the value name, type and value, if it exists.

2^>nul prevents the error text from appearing. ^ is the escape character that lets you put the > in the for command.

When I run the script above as given, I get this output:

Value Name = DefaultColor
Value Type = REG_DWORD
Value Value = 0x0

If I change the value of VALUE_NAME to BogusValue then I get this:

"HKEY_CURRENT_USER\Software\Microsoft\Command Processor"\BogusValue not found.
Sign up to request clarification or add additional context in comments.

6 Comments

In Windows 7, I needed to use skip=2
This works great except that I found I needed to change the "skip=4" to "skip=2". Windows 7 x64
the current solution has problems when the Value contains spaces - to fix this, use a wildcard for the last token: FOR /F "usebackq skip=2 tokens=1-2*
HKLM\Software have 32/64 bit versions. use /reg:64 and /reg:32 to access appropriate tree.
How about using for /f "usebackq tokens=1-2*" %%a IN ('^(reg query %KEY_NAME% /v %VALUE_NAME% ^| find "%VALUE_NAME%"^) 2^>nul')? Unless KEY_NAME contains VALUE_NAME this way there's no need to worry how many lines reg.exe prints before the value.
|
36

This works for me with a variable that contains spaces on Windows 7:

FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\Software\SomeAPP" /v ValueName`) DO (
    set appdir=%%A %%B
    )
ECHO %appdir%

Variable A contains all data before first space, B - rest part of ValueName (including further spaces), so appdir = ValueName

4 Comments

The 3* is important to make sure the entire reg value goes into %%B
I was getting an error with this code. Had to surround with quotes: set appdir="%%A %%B"
To be clear, if there is no space in the value, the "%%A %%B" returns a value with a space at the end.
Actually would be safer to do tokens=2* and SET appdir=%%B because the first space in the path might be adjacent to other spaces (e.g., C:\This is a weird path).
13

This one-liner is pretty much the same as your original try with a couple of additions. It works with paths including spaces, and works in both XP and Windows 7 even if the key is not found (and hides the error). %fn% will be empty if the key does not exist. This example gets the current desktop background filename:

for /f "tokens=2*" %%a in ('reg query "HKEY_CURRENT_USER\Control Panel\Desktop" /v Wallpaper 2^>^&1^|find "REG_"') do @set fn=%%b

This command uses tokens=2* with %%a as the loop variable but consumes %%b to correctly handle spaces. When using tokens=2*, the loop variable %%a is assigned the value in the second token (in this case, REG_SZ) and %%b is assigned the remainder of the line after the next group of delimiter characters, including all internal delimiter characters. This means that %%b will correctly replicate delimiter characters—even if multiple delimiter characters are clustered together. For example, the value might be C:\A weird path\blah.png. This technique of reading the value would correctly preserve the two spaces between C:\A and weird.

1 Comment

Is find available in all versions of windows? I would switch to findstr to be on the safe side.
9

Based on tryingToBeClever solution (which I happened to also stumble upon and fixed myself by trial-and-error before finding it), I also suggest passing the result output of reg query through find in order to filter undesired lines due to the ! REG.EXE VERSION x.y inconsistency. The find filtering and tokens tweaking also allows to pick exactly what we want (typically the value). Also added quotes to avoid unexpected results with key/value names containing spaces.

Final result proposed when we are only interested in fetching the value:

@echo off
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKCU\Software\Microsoft\Command Processor
set VALUE_NAME=DefaultColor
for /F "usebackq tokens=1,2,*" %%A IN (`reg query "%KEY_NAME%" /v "%VALUE_NAME%" 2^>nul ^| find "%VALUE_NAME%"`) do (
  echo %%C
)

A potential caveat of using find is that the errorlevel set by reg when errors occur is now obfuscated so one should only use this approach for keys known to be there and/or after a previous validation.

A tiny additional optimization (add skip=1 to avoid processing the first line of output) can be done in cases when the key name also contains the value name (as it is the case with HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion and CurrentVersion) but removes most flexibility so should only be used in particular use-cases.

1 Comment

It didn't support values with spaces. A minor adjustment was made on the tokens regarding that. Thanks for pointing that out!
6
@echo off
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKLM\SOFTWARE\Wow6432Node\Acme Software Inc\Common
set VALUE_NAME=InstallDir

FOR /F "tokens=2*" %%A IN ('REG.exe query "%KEY_NAME%" /v "%VALUE_NAME%"') DO (set pInstallDir=%%B)
echo %pInstallDir%

That works for me in Win7 where the key has a space and the value also has a space. So saving the above in c:\temp as test.bat, open a cmd window and run it.

C:\temp>test

C:\Program Files (x86)\acme Software Inc\APP\

Comments

5

For some reason Patrick Cuff's code doesn't work on my system (Windows 7) probably due to tryingToBeClever's comment. Modifying it a little did the trick:

@echo OFF

setlocal ENABLEEXTENSIONS
set KEY_NAME=HKEY_CURRENT_USER\Software\Microsoft\Command Processor
set VALUE_NAME=DefaultColor

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

if defined ValueName (
    @echo Value Name = %ValueName%
    @echo Value Type = %ValueType%
    @echo Value Value = %ValueValue%
) else (
    @echo %KEY_NAME%\%VALUE_NAME% not found.
)

Comments

4

For Windows 7 (Professional, 64-bit - can't speak for the others) I see that REG no longer spits out

! REG.EXE VERSION 3.0

as it does in XP. So the above needs to be modified to use

skip=2

instead of 4 - which makes things messy if you want your script to be portable. Although it's much more heavyweight and complex, a WMIC based solution may be better.

Comments

4

This works if the value contains a space:

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

if defined ValueName (
    echo Value Name = %ValueName%
    echo Value Type = %ValueType%
    echo Value Value = %ValueValue%
) else (
    @echo "%KEY_NAME%"\"%VALUE_NAME%" not found.
)

Comments

3

Great level of solutions here.

My little grain of salt as the solution @Patrick Cuff did not work out of the box; I had 2 problems

  • I use Windows 7 => changed to "skip=2"
  • The value of the registry value had a space in it Value Value = C:\Program Files\...

Here is the solution I found: taking 4 tokens and setting ValueValue to %%C and %%D. (Thanks @Ivan!)

setlocal ENABLEEXTENSIONS
set KEY_NAME="HKEY_CURRENT_USER\Software\Microsoft\Command Processor"
set VALUE_NAME=DefaultColor

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

if defined ValueName (
    @echo Value Name = %ValueName%
    @echo Value Type = %ValueType%
    @echo Value Value = %ValueValue%
) else (
    @echo "%KEY_NAME:"=%\%VALUE_NAME%" not found.
)

3 Comments

This was the best solution I found, works on Windows 7 64-bit. Thanks for your efforts
This will support one space in the value, but not multiple ones
@GaspardP Thanks for the comment! Hopefully, there won't be much with multiple spaces :)
3

To get a particular answer to the registry value you may use the following query:

REG QUERY "Key_Name" /v "Value_Name" /s

eg: REG QUERY "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v "EnableExtensions" /s

here /v : Queries for a specific registry key values.

/s : Queries all subkeys and values recursively (like dir /s)

Comments

0

Thanks, i just need to use:

SETLOCAL EnableExtensions

And put a:

2^>nul

Into the REG QUERY called in the FOR command. Thanks a lot again! :)

Comments

0
@echo off
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\awhost32.exe
set VALUE_NAME=Path
for /F "usebackq tokens=3" %%A IN (`reg query "%KEY_NAME%" /v "%VALUE_NAME%" 2^>nul ^| find "%VALUE_NAME%"`) do (
  echo %%A
)

How do you handle a space in the %%A variable? This results in C:\Program. The actual path is C:\Program Files\Symantec\pcAnywhere.

Comments

0
echo Off
setlocal ENABLEEXTENSIONS

set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup"
set VALUE_NAME=release 

REG QUERY %KEY_NAME% /S /v %VALUE_NAME%
endlocal

dot put \ at the end of KEY_NAME

1 Comment

This is an overly complex solution. The output is better if you just use /v %VALUE_NAME%
0

I've come across many errors on Windows XP computers when using WMIC (eg due to corrupted files on machines). Hence imo best not to use WMIC for Win XP in code. No problems with WMIC on Win 7 though.

Comments

0

You can get the value of a registry key as follows

@echo OFF
setlocal ENABLEEXTENSIONS
set REG_NAME="HKEY_CURRENT_USER\Software\Test"
set KEY_NAME=TestVal

FOR /F "usebackq skip=2 tokens=1-3" %%A IN (`REG QUERY %REG_NAME% /v %KEY_NAME% 2^>nul`) DO (
    @echo %%A : %%C
)
pause

those who wonder how to add reg keys, here is a way.

REGEDIT4

; @ECHO OFF
; CLS
; REGEDIT.EXE /S "%~f0"
; EXIT

[HKEY_CURRENT_USER\Software\Test]
"TestVal"="Succeeded"

Comments

0

With regedit:

@echo off
setlocal
::if the scrit is not ran as administrator
::  and the key does not require admin permissions
set __COMPAT_LAYER=RunAsInvoker

set "key=%~1"
set "value=%~2"

regedit /e "#.reg" "%key%"


for /f "tokens=1,* delims==" %%a in ('find  """%value%""=" "#.reg"') do if "%%~b" neq "" echo %%~b
del /q #.reg

endlocal

Example:

call regreader.bat "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup\1033\" Version

output:

3.0.30729.4926

Comments

-1
set regVar_LocalPrjPath="LocalPrjPath"
set regVar_Path="HKEY_CURRENT_USER\Software\xyz\KeyPath"

:: ### Retrieve VAR1 ###
FOR /F "skip=2 tokens=2,*" %%A IN ('reg.exe query %regVar_Path% /v %regVar_LocalPrjPath%') DO set "VAR1=%%B"

1 Comment

this doesn't work if you are getting the default key and the windows locale is french. by doing this, you are using space as a separator, so the key name (Default) is named (Par Defaut) (french) with a space in the middle, yes, so instead of tokens=2, you'll need tokens=3
-1

You can also use this solution with a single command line:

VARIABLE=$(reg query "HKLM\REGISTRYKEYPATH" /v "REGISTRY KEY" | grep -i "REGISTRY KEY" | awk '{print $NF;}')

For your information $NF retrieves the last field (which is the registry key value).

4 Comments

I don't believe this will work out of the box on an unmodified Windows XP machine. What prerequisites are required to make this work?
I tested on Windows 10 without any prerequisites.
This could work (I have grep and awk avaliable from git/msys64/cygwin), however, it breaks if the value contains spaces/tabs, for example "OneDrive - CompanyName", in this case I will get "CompanyName" only
I ended up with awk '{$1=$2=""; print $0;}' which will ignore the first two columns and print everything else