Issues with batch file to search registry and edit - batch-file

I'm not so new to batch scripting and have done a small amount of scripts for various other things but this script has stumped me.
I've actually pulled this idea from somewhere else as I'm not that deep into the for commands just yet.
What I'm trying to do with this script is search every subkey within the HKU rootkey for a specific subkey path. If that subkey path exists it'll modify a key value within that subkey path. But it seems to keep failing with no error.
This is what I have right now:
for /f %%a in ('reg query hku') do call :loop1 %%a
goto :end
:loop1
for /f %1 in (reg query %1\software\microsoft\dynamics) do call :loop2 %%b
goto :end
:loop2
if Errorlevel 1 goto :error
reg add %1\6.0\configuration /v configurationfile /t reg_sz /d \ /f
goto :end
:error
echo Error has occurrd.
goto :end
:end
Pause
When I run this batch I get the following.
c:\Users\-username-\Desktop\test>for /F %a in ('reg query hku') do call :loop1 %a
c:\Users\-username-\Desktop\test>call :loop1 HKEY_USERS\.DEFAULT
c:\Users\-username-\Desktop\test>for /f HKEY_USERS\.DEFAULT in (reg query HKEY_USER
S\.DEFAULT\software\microsoft\dynamics) do call :loop2 %b
c:\Users\-username-\Desktop\test>
It seems like it just stops running? when I check the errorlevel after it runs it returns "0" so I'd think I'd at least see the error message come up?
Am I missing something small I'm just looking over?

Run this to start with - see if what it returns is helpful to you:
This may need a later version of Windows - I'm not sure of the reg query options for earlier windows.
#echo off
for /f "delims=" %%a in ('reg query hku /s /f data /k ^| find /i "\software\microsoft\dynamics" ') do echo "%%a"

You need GOTO :eof to return from the subroutines.
for /f %%a in ('reg query hku') do call :loop1 "%%a"
pause
goto :eof
:loop1
for /f "%~1" in (reg query "%~1\software\microsoft\dynamics") do call :loop2 "%%b"
goto :eof
:loop2
if Errorlevel 1 echo Error has occurred. & pause & exit /B 1
reg add "%~1\6.0\configuration /v configurationfile" /t reg_sz /d \ /f
goto :eof

I found the bug(s). It was two places. RGuggiesberg, you are right. I needed the EOF in there. As foxidrive points out, the first line of "loop1" had some syntax issues. I was confusing myself.
Replaced:
for /f %1 in ('reg query %1\software\microsoft\dynamics') do call :loop2 %%b
with:
for /f %%b in ('reg query %1\software\microsoft\dynamics') do call :loop2 %%b
Now it's working fine. Thanks for the pointers!

Related

For /F binary reg value neq (result = always success)

What I'm I missing?
I try to grab a binary key value from UserPreferencesMask, the binary value is 9032078010000000 (or hex:90,32,07,80,10,00,00,00 in regedit).
Result %%A does print 9032078010000000, but when I use this result in/with if %% NEQ or EQU I always goto:HEX_okay.
for /f "skip=2 tokens=3 delims= " %%A in ('reg query "HKCU\Control Panel\Desktop" /f UserPreferencesMask /d /T REG_BINARY') do (
echo.RESULT="%%A"
REM if %%a NEQ 9032078010000000 goto FiX
if %%A EQU 9032038010000000 goto HEX_okay
goto:FiX
)
I use skip=2 because I don't use the first 2 lines,
and delims= " to skip to the 3rd token, sort of speak...
edit:
The UserPreferencesMask has to be 9032078010000000 (binary value), if not, change it to this specific binary value (use reg add).
ie. REG.exe ADD "HKCU\Control Panel\Desktop" /V "UserPreferencesMask" /T REG_BINARY /D "9032078010000000" /F
I also tried:
for /f "tokens=3" %%i in ('reg query "HKCU\Control Panel\Desktop" /v UserPreferencesMask /t REG_BINARY') do (
echo.RESULT="%%i"
IF NOT %%i equ 9032038010000000 goto FiX
IF %%i equ 9032038010000000 goto HEX_okay
goto:DO_NOTING
)
...But with same result and changing equ into == doesn't help either.
when I change the value for UserPreferencesMask in regedit and place aa (or what ever) I do get some result; goto FiX. BUT when I just add some numbers (in regedit) then I always goto HEX_okay, so annoying :'(
These next changes (below) don't help either, then it's always, goto FIX:
IF NOT "%%i"=="9032038010000000" goto FiX
IF "%%i"=="9032038010000000" goto HEX_okay
These next lines do seem to "work", WELL SORT OFF:
when I change the binary value of "UserPreferencesMask" like a lot than just 1 or 2 digits, then it does seem to work as expected...
Weird and not completely 'monkey proof', it's NOT always doing as expected.
for /f "skip=2 tokens=3 delims= " %%i in ('reg query "HKCU\Control Panel\Desktop" /F "UserPreferencesMask" /D /C /E /T REG_BINARY') do (
echo.RESULT="%%i"
IF NOT %%i equ 9032038010000000 goto FiX
IF %%i equ 9032038010000000 goto HEX_okay
goto:NO_UserPreferencesMask
)
PS. I can use for /f "tokens=3" for the same result though
This workaround does seem to function though:
reg query "HKCU\Control Panel\Desktop" /F "UserPreferencesMask" /D /C /E /T REG_BINARY | find /i "9032078010000000"
if errorlevel 1 goto FiX
if errorlevel 0 goto HEX_okay
Here's how I would do it using Reg.exe in a For loop:
#Echo Off
Set "DUPM=9032078010000000"
Set "MASK="
For /F "EOL=H Tokens=2*" %%A In (
'Reg Query "HKCU\Control Panel\Desktop" /V UserPreferencesMask'
) Do If /I Not "%%B"=="%DUPM%" Set "MASK=%%B"
If Not Defined MASK GoTo HEX_okay
:FiX
Echo The value data %MASK% needs fixing!
Pause
GoTo :EOF
:HEX_okay
Echo The value data matches %DUPM%!
Pause
GoTo :EOF
EditBased upon your comment, and given that you're still not using the Reg Query options correctly/efficiently, here is how you should perform that task:
#Echo Off
Reg Query "HKCU\Control Panel\Desktop" /V UserPreferencesMask|Find /I "9032078010000000" >Nul && GoTo HEX_okay
:FiX
Echo The value data needs fixing!
Pause
GoTo :EOF
:HEX_okay
Echo The value data matches!
Pause
GoTo :EOF
Side note: as mentioned in my comments why aren't you simply adding the key? If the existing key matches, overwriting it will not matter, if it doesn't you've changed it:
Reg Add "HKCU\Control Panel\Desktop" /V UserPreferencesMask /T REG_BINARY /D 9032078010000000 /F>Nul

How to get Java version in a batch script subroutine?

From this question:
for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do (
#echo Output: %%g
set JAVAVER=%%g
)
How can I put this into a subroutine and call it, passing a path to the java executable? Here's an example of my problem:
#echo off
setlocal enabledelayedexpansion
call :GET_JAVA_VER "java"
goto END
:GET_JAVA_VER
for /f "tokens=3" %%g in ('%1 -version 2^>^&1 ^| findstr /i "version"') do #echo %%g
%1 -version 2>&1 | findstr /i "version"
goto :EOF
:END
endlocal
This outputs:
The filename, directory name, or volume label syntax is incorrect.
java version "10.0.1" 2018-04-17
It seems to me that the for loop is evaluating the parameter (%1) differently.
What's the difference?
EDIT
Possible duplicate of Java Version in a batch file
According to this answer, if that is indeed the problem, I would have to somehow transform the passed in path by adding quotes around each directory containing spaces. That sounds like a pain and I'm hoping there's another explanation; I still don't get why in this case just passing in "java" doesn't work.
(Note: using usebackq and back-quotes makes no difference)
It seems that piping the output to findstr was stripping the quotes for some reason. I deduce this because when I removed the ^| findstr /i "version" portion, this:
#echo off
setlocal enabledelayedexpansion
call :GET_JAVA_VER "java"
goto END
:GET_JAVA_VER
for /f "tokens=3" %%g in ('%1 -version 2^>^&1') do #echo %%g
goto :EOF
:END
endlocal
Outputs this:
"10.0.1"
Runtime
64-Bit
This modified script works (with full paths as well):
#echo off
setlocal enabledelayedexpansion
call:GET_JAVA_VER "java"
goto END
:GET_JAVA_VER
for /f "tokens=3" %%g in ('%~1 -version 2^>^&1') do (
echo %%~g
rem Stop after first line
goto :EOF
)
goto :EOF
:END
endlocal

Batch File Skipping over FOR LOOP

UPDATE
I removed the tokens=4 and it started outputting data. It is not skipping past the FOR LOOP. I was skipping too far ahead with the tokens. I am still a little confused as to why it works as a single batch and not from this batch but now at least I know what the issue was. Thank you to everyone that was looking into this for me.
I am writing a script to copy over data from one computer to another. The issue is that it is skipping over the FOR LOOP that I am calling from another FOR LOOP. If you are testing the script it requires two PC's and a mapped T: drive to somewhere on the second computer. I can write the script so it looks for an external drive if that is more helpful to someone.
FOR /F "tokens=4 skip=1" %%a in ('REG QUERY "%_regshell%" /v "%_regdesktop%"') DO (
SET _dt=%%a
echo robocopy "!_dt!" "!_NetworkDrive!\!_fndesktop!" !_params!
echo attrib -h -r "!_NetworkDrive!\!_fndesktop!"
)
If I write the FOR LOOP above in a batch by itself and just echo out %%a then it works without a problem. In this, I can see that it is indeed calling :_backup but it skips directly over the FOR Loop and I am not sure why. I have written scripts like this many times but never had any that just completely ignore the FOR Loop. Can anyone take a look and assist? Thank you.
#echo off
:: Set Variables
SET _driveID=T:
SET _params=/Z /E /COPY:DT /R:1 /W:0 /XD LocalService NetworkService temp "temporary internet files" winsxs Content.IE5 cache /XF ntuser.* *.tmp /XJ /FP /NC /NS /NP /NJH
SET _regshell=HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
SET _regdesktop=Desktop
:: Set Current Directory
pushd %SystemDrive%\
:: Start Menu - Create Choices and Options. Send to various places to perform the actions.
:_start
cls
ECHO Please type either option 2 or 3 and then press ENTER on the keyboard?
Echo 2. TRANSFER FILES FROM DESKTOP TO LAPTOP
Echo 3. EXIT THE PROGRAM
echo.
set /p choice=Enter Number:
if '%choice%'=='2' goto _desktopToLaptop
if '%choice%'=='3' goto :EOF
echo "%choice%" is not a valid option. Please try again
echo.
goto _start
:: Detect Drive Letters
:_desktopToLaptop
setlocal EnableDelayedExpansion
FOR /F "usebackq skip=1" %%a IN (`WMIC logicaldisk where DeviceID^="%_driveID%" get caption`) DO (
SET _NetworkDrive=%%a
if exist %%a (
CALL :_backup
goto :EOF
) else (
echo.
echo The laptop does not appear to be attached to the computer.
echo.
pause
goto :EOF
)
)
:_backup
:: Detect the folder locations and begin to backup each location to the laptop.
FOR /F "tokens=4 skip=1" %%a in ('REG QUERY "%_regshell%" /v "%_regdesktop%"') DO (
SET _dt=%%a
echo robocopy "!_dt!" "!_NetworkDrive!\!_fndesktop!" !_params!
echo attrib -h -r "!_NetworkDrive!\!_fndesktop!"
)
echo we are past the for loop
pause
:: Return to directory program was run from
popd
If anyone else runs into this issue or something similar, check your tokens and your skip. Mine worked just fine as a single batch but when I included as a call I had to change the options from tokens=4 skip=1 to tokens=3* skip=2 in order to get the correct output.
The correct tokens in that FOR LOOPS should be:
#echo off
:: Set Variables
SET _driveID=T:
SET _params=/Z /E /COPY:DT /R:1 /W:0 /XD LocalService NetworkService temp "temporary internet files" winsxs Content.IE5 cache /XF ntuser.* *.tmp /XJ /FP /NC /NS /NP /NJH
SET _regshell=HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
SET _regdesktop=Desktop
:: Set Current Directory
pushd %SystemDrive%\
:: Start Menu - Create Choices and Options. Send to various places to perform the actions.
:_start
cls
ECHO Please type either option 2 or 3 and then press ENTER on the keyboard?
Echo 2. TRANSFER FILES FROM DESKTOP TO LAPTOP
Echo 3. EXIT THE PROGRAM
echo.
set /p choice=Enter Number:
if '%choice%'=='2' goto _desktopToLaptop
if '%choice%'=='3' goto :EOF
echo "%choice%" is not a valid option. Please try again
echo.
goto _start
:: Detect Drive Letters
:_desktopToLaptop
setlocal EnableDelayedExpansion
FOR /F "usebackq skip=1" %%a IN (`WMIC logicaldisk where DeviceID^="%_driveID%" get caption`) DO (
SET _NetworkDrive=%%a
if exist %%a (
CALL :_backup
goto :EOF
) else (
echo.
echo The laptop does not appear to be attached to the computer.
echo.
pause
goto :EOF
)
)
:_backup
:: Detect the folder locations and begin to backup each location to the laptop.
FOR /F "tokens=3* skip=2" %%a in ('REG QUERY "%_regshell%" /v "%_regdesktop%"') DO (
SET _dt=%%a
echo robocopy "!_dt!" "!_NetworkDrive!\!_fndesktop!" !_params!
echo attrib -h -r "!_NetworkDrive!\!_fndesktop!"
)
echo we are past the for loop
pause
:: Return to directory program was run from
popd
Given that the main issue in your script appears to be the setting of a variable to the data within the defined registry key and value, you could use:
Set "_regshell=HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
Set "_regdesktop=Desktop"
Set "_dt="
For /F "EOL=H Tokens=2*" %%A In ('Reg Query "%_regshell%" /V "%_regdesktop%"'
) Do Set "_dt=%%~B"
If Not Defined _dt GoTo :EOF
Echo "%_dt%"

.Bat/CMD - Hiding "ERROR" with reg.exe >nul 2>&1

FOR /F "tokens=2*" %%A IN (
'REG QUERY "HKLM\Software\EA GAMES\Need for Speed Most Wanted" /v InstallDir'
) DO (set HBMU=%%B)
GOTO END
how I can add If %ERRORLEVEL% == 1 goto CLOSE to my code? because when i put under ) DO (set HBMU=%%B) it does not work.
Try this, after completing the rest of the registry key on line 2:
For /F "Skip=1 Tokens=2*" %%A In (
'Reg Query "HKLM\SOFTWARE\..." /V "InstallDir" 2^>Nul'
) Do Set "HBMU=%%B"
You cannot redirect both to Nul otherwise nothing will be output from the loop as variable %%B
Edit
Here's a complete script which should do what your commented code was supposed to do. (As long as your software definitely places it's information in the registry according to the Operating System architecture).
#Echo Off
Set "EAG=EA GAMES\Need for Speed Most Wanted"
Set "RKM=\"
Reg Query "HKLM\Hardware\Description\System\CentralProcessor\0"^
/V "Identifier" 2>Nul|Find /I "x86">Nul||Set "RKM=\Wow6432Node\"
For /F "EOL=HTokens=2*" %%A In ('Reg Query "HKLM\Software%RKM%%EAG%" /V^
"InstallDir" 2^>Nul') Do Start "" "%%~B\unins000.exe"
Pause

Getting errorlevel from usebackq

i've ran into a problem with adding registry keys using reg.exe via batch.
I'm using this:
FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\iNiT" /v Basic`) DO (
SET BASICVALUE=%%A %%B
)
ECHO ERROR: %ERRORLEVEL%
EDIT:
Normaly REG.exe outputs a errorlevel when executed;
0 - Successful
1 - Failed
And i get:
ERROR:
Somehow the errorlevel gets wiped or not saved.
I need to get the %errorlevel% out of it when executed, how do i do this, this dosn't seem to work.
Can you somehow set the errorlevel to a variable? I've tested this:
FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\iNiT" /v Basic && SET ERROR=%ERRORLEVEL%`) DO (
SET BASICVALUE=%%A %%B
)
ECHO %ERROR%
Nor does that work.
%% wasn't expected
Any information would be helpful :)
REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\iNiT" /v Basic > tempFile.txt
echo %errorlevel%
FOR /F "usebackq tokens=3*" %%A IN (tempFile.txt) DO (
SET BASICVALUE=%%A %%B
)
I've used the below code in one of my script and may answer your question -
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\VisualSVN\VisualSVN Server" /V RepositoriesRoot >nul 2>&1 & if %errorlevel%==1 (echo.Visual SVN not installed)
Cheers, G

Resources