72

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

Patrick Cuff
  • 28,540
  • 12
  • 67
  • 94

18 Answers18

69

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.
Patrick Cuff
  • 28,540
  • 12
  • 67
  • 94
  • 31
    In Windows 7, I needed to use `skip=2` – Saul Feb 19 '12 at 00:17
  • 9
    This works great except that I found I needed to change the "skip=4" to "skip=2". Windows 7 x64 – Jason Duffett May 03 '12 at 10:34
  • You can replace the line with value not found with the following in order to remove the ugly double quote: @echo "%KEY_NAME:"=%\%VALUE_NAME%" not found. – Jean-Francois T. Dec 11 '14 at 11:53
  • 11
    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*` – TmTron Jun 15 '15 at 09:43
  • 2
    `HKLM\Software` have **32/64 bit** versions. use `/reg:64` and `/reg:32` to access appropriate tree. – befzz Jul 13 '16 at 18:27
  • 2
    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. – Paul B. Sep 13 '17 at 08:42
34

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

Andreas
  • 5,393
  • 9
  • 44
  • 53
Ivan
  • 1
  • 2
  • 2
  • The `3*` is important to make sure the entire reg value goes into `%%B` – icc97 Mar 02 '17 at 21:54
  • I was getting an error with this code. Had to surround with quotes: set appdir="%%A %%B" – uzrgm Oct 09 '17 at 16:28
  • 1
    To be clear, if there is no space in the value, the "%%A %%B" returns a value with a space at the end. – Kipp Jun 17 '20 at 20:01
  • 2
    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`). – binki Jan 25 '21 at 19:06
12

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.

binki
  • 7,754
  • 5
  • 64
  • 110
ChevyNo1
  • 1
  • 1
  • 3
  • Is find available in all versions of windows? I would switch to findstr to be on the safe side. – NiKiZe Jun 16 '21 at 08:03
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.

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\

sheir
  • 393
  • 4
  • 9
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.
)
niels
  • 760
  • 8
  • 25
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.
)
Andrew S
  • 426
  • 5
  • 6
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.

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.
)
Jean-Francois T.
  • 11,549
  • 7
  • 68
  • 107
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)

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.

wickedone
  • 542
  • 1
  • 6
  • 18
Tom
  • 1
  • 1
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

jacob justin
  • 156
  • 1
  • 5
  • This is an overly complex solution. The output is better if you just use /v %VALUE_NAME% – Ian M Oct 27 '15 at 00:20
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.

unseen_rider
  • 324
  • 5
  • 23
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"
Sameera R.
  • 4,384
  • 2
  • 36
  • 53
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! :)

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

npocmaka
  • 55,367
  • 18
  • 148
  • 187
-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"
mega6382
  • 9,211
  • 17
  • 48
  • 69
  • 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` – cfaz Mar 06 '20 at 12:55
-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).

user9541033
  • 13
  • 2
  • 6
  • 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? – Amish Programmer Apr 28 '21 at 14:23
  • I tested on Windows 10 without any prerequisites. – user9541033 Apr 30 '21 at 08:55
  • 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 – lastr2d2 Jul 20 '21 at 06:07
  • I ended up with `awk '{$1=$2=""; print $0;}'` which will ignore the first two columns and print everything else – lastr2d2 Jul 20 '21 at 06:25