Search for data value with Reg.exe and delete parent key - batch-file

I am currently trying to use reg query commands to find the data value "teststring" in a value with a random name in HKCU\Software\random characters. I want the script to find the teststring value and then delete the parent key HKCU\Software\random characters. I have tried various ways with scripting and this is what I have so far, however I keep getting syntax errors and can't get reg query to find what I need it to:
#echo off
setlocal enabledelayedexpansion
set Key="HKCU\Software"
set STRING="teststring"
for /f "delims=" %%a in ('reg.exe query "%Key%" /f "%STRING%" /d /s') do (
call :GetValueName Value "%%a"
ECHO reg.exe delete "%Key%" /v "!Value!" /f
)
goto :eof
:GetValueName
set Return=
for %%a in (%~2) do (
if "%%a"=="REG_SZ" (
set %1=!Return:~1!&goto :eof
) else (
set Return=!Return! %%a
)
)
:eof

Here's a simpler way to do it.
Remove the ECHO (not the echo) AFTER you are satisfied with what is displayed.
#echo off
set "Key=HKCU\Software"
set "STRING=teststring"
for /f "delims=" %%a in ('reg query "%Key%" /v test /s /d /f "%STRING%" /t REG_SZ') do (
echo %%a | findstr /v "REG_SZ" | findstr /v /c:"End of search:" >nul && ECHO reg.exe delete "%%a" /f
)
pause

Related

Find first subkey that has specific value

I am struggling to finish up this batch file and I am not sure what I am missing, although I am certain it's a small mistake. I think it's with my delims or possibly the subkey naming convention.
#echo off
#echo 12 (2014)
#echo 13 (2016)
#echo 14 (2017)
#echo 15 (2019)
set /p "version=Enter Version: "
set "value_name=ParentInstance"
set "value_data=MSSQL%version%E.LOCALDB"
set "key_path=HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SQL Server\UserInstances"
for /f "tokens=2* delims={}" %%a in ('reg query "%key_path%" /s 2^>nul') do (
for /f "tokens=2*" %%b in ('reg query "%%b" /v "%value_name%" 2^>nul') do (
set "subkey=%%b"
goto :break
)
)
:break
if defined subkey (
reg add "%subkey%" /v "%value_name%" /t REG_SZ /d "%value_data%" /f
echo Updated Value data of key : %subkey% to : %value_data%
) else (
echo Subkey with value name "%value_name%" not found.
)
endlocal
TIMEOUT /t 5 /nobreak
I am looking for a way to retrieve all subkeys under
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SQL
Server\UserInstances
Then for each subkey check if it has a value named "ParentInstance" by querying the value under that subkey. If it finds any, it stores that subkey in the variable "subkey", then uses the reg add command to change the data of the value named "ParentInstance" to the value in the variable "value_data" which is "MSSQL%version%E.LOCALDB" (%version% is a number that gets input).
Example of Registry (UserInstances may include multiple subkeys)
To perform the task using the same methodology you laid out in your question:
Get all next level subkeys within your %key_path%, (I added some additional robustness targeting only those child keys with the format {*-*-*-*-*}).
For each of those subkeys, query if it has a value named %value_name%.
If it finds any, change the value data for %value_name% for that subkey using the reg add command to the content of the variable, %value_data%.
For /F "Delims=" %%G In ('%SystemRoot%\System32\reg.exe Query "%key_path%" /F "{*-*-*-*-*}" 2^>NUL ^| %SystemRoot%\System32\find.exe "\"') Do %SystemRoot%\System32\reg.exe Query "%%G" /F "%value_name%" /V /E 2>NUL 1>&2 && %SystemRoot%\System32\reg.exe Add "%%G" /V "%value_name%" /D "%value_data%" /F 1>NUL
set "key_path=HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SQL Server\UserInstances"
for /f "tokens=2* delims={}" %%a in ('reg query "%key_path%" /s 2^>nul') do (
echo %%%% a=%%a %%%% b=%%b
for /f "tokens=2*" %%B in ('reg query "%%b" /v "%value_name%" 2^>nul') do (
echo %%%% B=%%B %%%% C=%%C
set "subkey=%%b"
goto :break
)
)
Note that the metavariables a, b, B and C is one of the few instances in batch where case is significant. %%b and %%B are different variable.
See for /? from the prompt for documentation.
for /f "tokens=2,*delims={}" %%u... will parse the text line in question, assign the second "token" to %%u and the rest-of-the-line-after-token-2 (*) to %%v.
Tokens are calculated left-to-right from the format {delimiters}token1{delimiters}token2{delimiters}token3{delimiters}token4... - leading delimiters optional, and {delimiters} is any string of any delimiter specified between delims= and ".

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

.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

Saving output of a batch file on network location

I have lifted bits and pieces of the code from multiple places and have made the below code.
The functionality of this code is basically to read all softwares and save it in a csv format so I can use it further. I want the code to save output on a folder which is on another computer which is shared on the domain. Below is the code:
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set OutputFile=C:\Domo\%computername%.csv
echo "Computer","Key","Version","Name","Publisher">"%OutputFile%"
call :getsw "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
call :getsw "HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall"
call :getsw "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
ENDLOCAL
exit /b
:getsw
for /F "delims=" %%g in ('reg query "%~1" 2^>NUL') do (
set "_swRegKey=%%~g"
set "_swName="
set "_swVers="
set "_swPub="
for /F "tokens=1,2,*" %%G in ('
reg query "%%~g" /V DisplayName 2^>NUL ^| findstr /I "DisplayName"
') do set "_swName=%%~I"
for /F "tokens=1,2,*" %%G in ('
reg query "%%~g" /V DisplayVersion 2^>NUL ^| findstr /I "DisplayVersion"
') do set "_swVers=%%~I"
for /F "tokens=1,2,*" %%G in ('
reg query "%%~g" /V Publisher 2^>NUL ^| findstr /I "Publisher"
') do set "_swPub=%%~I"
call :echosw
)
exit /b
:echosw
if "!_swName!!_swVers!"=="" (
echo "%COMPUTERNAME%","unknown","!_swRegKey!","","">>"%OutputFile%"
) else (
echo "%COMPUTERNAME%","!_swRegKey!","!_swVers!","!_swName!","!
_swPub!">>"%OutputFile%"
)
exit /b
The problem is when I change the location of outputfile (Line 3) from C:\Domo\%computername%.csv to a network location like \Win-p0sck5u2hqd\csv\%computername%.csv
This gives an error saying access is denied while executing the batch file. Is there anything I am missing. please help me understand why it is not working and is there any solution.
This location \Win-p0sck5u2hqd\ is accessible from my run command.

reg query a key value based on another key value

What I'm trying to do is have a batch script return the uninstall link for a program. So basically I want something like this:
Select UninstallString from HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall where DisplayName='Sublime Text 1.0"
I'm using
reg query HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /S^|find " DisplayName"
to initially get a list of programs, which then get put in a menu, then I select the program to uninstall and it's supposed to go to that program's registry in HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall and get it's UninstallString value
Try this:
#echo off&setlocal enabledelayedexpansion
set "regroot=HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
set "file=%~dpn0.txt"
set /a fcount=0
for /f "delims==" %%i in ('set $ 2^>nul') do set "%%i="
if exist "%file%" (
for /f "usebackqtokens=1*delims=|" %%i in ("%file%") do (
set /a fcount+=1
set "$d%%j=%%j"
set "$u%%j=%%i"
)
goto:menu
)
echo(building "%file%", please wait
for /f "delims=" %%i in ('reg query "%regroot%"') do (
set "DN="& set "US="
for /f "tokens=2*" %%j in ('reg query "%regroot%\%%~ni" /v DisplayName 2^>nul^|find /i "DisplayName"') do set "DN=%%~k"
for /f "tokens=2*" %%j in ('reg query "%regroot%\%%~ni" /v UninstallString 2^>nul^|find /i "UninstallString"') do set "US=%%~k"
if not "!DN!"=="" if not "!US!"=="" if not defined $d!DN! (
>>"%file%" echo(!US!^|!DN!
set /a fcount+=1
set "$d!DN!=!DN!"
set "$u!DN!=!US!"
<nul set/p"=."
)
)
echo(
:menu
echo(%fcount% programs with uninstall strings found.
:loop
set /a pcount=0
set "program="
set /p "program=type a program name (q=quit): "
if not defined program goto:loop
if "%program%"=="q" goto:eof
echo(
for /f "tokens=2delims==" %%i in ('set $d ^|findstr !program! 2^>nul') do (
echo(%%i
echo(!$u%%i!
echo(
set /a pcount+=1
)
if %pcount% equ 0 (echo(!program! not found.) else echo(%pcount% program(s^) found.
goto:loop
You can use some of findstr's REGEX capabilities (eg. /i for case insensitive search). Please note: to search for all programs starting with "M" you can use "^$dM" or /b $dM. Searchable strings have always a leading $d.
Try this "two-liner":
for /f "tokens=7 delims=\" %%a in ('reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /S /F "MySoftware" ^| find "{"') do set ProgramUninstallRegKey=%%a
for /f "skip=1 tokens=3*" %%a in ('reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\%ProgramUninstallRegKey% /V "UninstallString"') do set ProgramUninstallString=%%a %%b

Resources