Find first subkey that has specific value - batch-file

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 ".

Related

REG QUERY combined with FOR return Half of what I need

I have a registry key created by InnoSetup during installation. This key contains two information :
DisplayName
QuietUninstallString
I don't know what is the full name of my Key. The only informations I have is the path :
"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
and the value of the key "DisplayName" (MyApplicationName).
What I need to do, is to retrieve the "QuietUninstallString" value, which is supposed to be a path with "/SILENT" at the end of the path.
Right now I wrote this batch file :
#echo off
setlocal enableextensions disabledelayedexpansion
set tosearch=%1
for /f "tokens=3" %%a in ('
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /s /f %tosearch% ^| findstr "QuietUninstallString"
') do set "value=%%a"
echo %value%
And I call it like this :
test.bat MyApplicationName
Problem is, when I run this file, it return :
"C:\Program
While I want this to be returned :
"C:\Program Files (x86)\MyFolder\MyApplicationName\unins000.exe" /SILENT
Is there a better way to retrieve the information with my batch file ?
Based upon what you've posted, you should be able to replace your entire code with this:
#For /F "EOL= Delims=" %%G In ('%SystemRoot%\System32\reg.exe Query
"HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" /S /F
"%~1" /E /D 2^>NUL') Do #For /F "Tokens=2,*" %%H In (
'%SystemRoot%\System32\reg.exe Query "%%G" /V "QuietUninstallstring" 2^>NUL'
) Do #Echo(%%I
Or if the intention is to actually run the uninstall string:
#For /F "EOL= Delims=" %%G In ('%SystemRoot%\System32\reg.exe Query
"HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" /S /F
"%~1" /E /D 2^>NUL') Do #For /F "Tokens=2,*" %%H In (
'%SystemRoot%\System32\reg.exe Query "%%G" /V "QuietUninstallstring" 2^>NUL'
) Do #Start "" %%I
Use tokens=2,* and set "value=%%b". See for /? from the prompt for documentation

Batch / REG QUERY get the path of found value

I am trying to make a batch file, that finds a specific interface (their name vary from computer to computer = query). To find the interface I use a specific IP that is under that interface as a value.
The code here can find the interface in question based on the IP i insert into "IP-ADDRESS".
But my ultimate goal is to based on this search add two registry values into this interface, and therefore I need the path.
How do I get the path into a variable based on the search below?
for /f "tokens=3*" %%a in ('reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\ /s /f "IP-ADDRESS"') do set Myvar=%%b
ECHO %Myvar%
PAUSE
Thank you in advance!
The following batch-file returns here:
> Q:\Test\2018\11\16\SO_53340832.cmd
IPADDRESS:192.168.56.1 on interface:{4fe80965-dda5-466a-801d-14937fd3829c}
It uses "tokens=1,2*" and /v IPADDRESS without dash.
:: Q:\Test\2018\11\16\SO_53340832.cmd
#Echo off & SetLocal EnableExtensions EnableDelayedExpansion
Set "Key=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"
Set "Val=IPADDRESS"
For /f "tokens=1,2*" %%A in (
'reg query "%Key%" /s /v "%Val%" ^| findstr /i "^HKEY %Val%"'
) Do if /i "%%A" neq "%Val%" (rem must be HKEY
Set "Interface=%%A"
) Else (
Echo %VAL%:%%C on interface:!Interface:%Key%\=!
)
Here's one possibility for you:
#Echo Off
Set "RKP=HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"
Set "RVD=172.26.193.3"
Set "RKC="
For /F "Delims=}" %%A In ('Reg Query "%RKP%" /S /F "%RVD%" /D 2^>Nul'
) Do If Not Defined RKC Set "RKC=%%A}"
If Not Defined RKC Exit /B
Rem show the variable and value for five seconds
Set RKC
Timeout 5 >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

batch command - find multiple texts in seperate lines and output them as columns

i am trying to make an inventory of installed software in domain PCs by following reg command
Reg Query HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall /S ^| Find /I "DisplayName"
I am using Find /I "DisplayName" to get software-name. I also need the version number (and may be few more fields later), but its in another line as DisplayVersion.
Since I am running this on multiple computers, my script looks like this:
for /f %%i in (computers_ALL.txt) do (
for /f "tokens=1,2,*" %%j in ('psexec \\%%i Reg Query HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall /S ^| Find /I "DisplayName"') do (
echo x64 %%i %%l >>%OUTPUT_FILE%
)
for /f "tokens=1,2,*" %%j in ('psexec \\%%i Reg Query HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /S ^| Find /I "DisplayName"') do (
echo x86 %%i %%l >>%OUTPUT_FILE%
)
)
Now I can only find DisplayName. How can I find DisplayVersion which is on another line and add it to second column? My output will be like,
ComputerName, Platform (32-64 bit), Software Name, Software Version
I can take care upto software-name, but having difficulty to get version and put it on second column. Appreciate your help. Thanks.
Following script works against a local Windows machine. Adapting it for a list computers_ALL.txt instead of "%computername%" and adding psexec \\%_comp% should be a simple task.
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "OUTPUT_FILE=%temp%\41887529.txt"
for /F %%i in ("%computername%") do (
set "_comp=%%i"
call :proHive "x64" "\Software\Microsoft\Windows\CurrentVersion\Uninstall"
call :proHive "x86" "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
)
rem debugging output
type "%OUTPUT_FILE%"
ENDLOCAL
goto :eof
:proHive
rem %1 platform
rem %2 registry key
>>"%OUTPUT_FILE%" (
for /f "tokens=*" %%G in ('
Reg Query "HKLM%~2" /S /V DisplayName ^| Find /I "HKEY_LOCAL_MACHINE%~2"
') do (
set "_DisplayName="
set "_DisplayVersion="
for /f "tokens=1,2,*" %%j in ('
Reg Query "%%G" ^| Findstr /I "DisplayName\> DisplayVersion\>"') do set "_%%j=%%l"
SETLOCAL EnableDelayedExpansion
echo %_comp%,%~1,!_DisplayVersion!,!_DisplayName!
ENDLOCAL
)
)
goto :eof
#ECHO OFF
SETLOCAL
SET "output_file=u:\report.txt"
DEL "%output_file%" /F /Q
for /f %%i in (q41887529.txt) do (
SET "compname=%%i"
CALL :clrsoft
FOR %%z IN (\ \Wow6432Node\) DO (
for /f "tokens=1,2,*" %%j in (
'Reg Query HKLM\Software%%zMicrosoft\Windows\CurrentVersion\Uninstall /S ^| Findstr /I "DisplayName DisplayVersion HKEY_LOCAL_MACHINE\\"'
) do (
IF /i "%%j"=="Displayname" (
SET "softname=%%l"
) ELSE (
IF /i "%%j"=="Displayversion" (
SET "softver=%%l"
) ELSE (
CALL :report %%z
)
)
)
REM processed all data - final report
CALL :report %%z
)
)
GOTO :EOF
:: Report routine parameters :
:: %1 indicates x64 ("\") or x86 (\Wow6432Node\)
:report
IF NOT DEFINED softname GOTO clrsoft
IF "%1"=="\" (
ECHO "%compname%",x64,"%softname%","%softver%">>"%output_file%"
) ELSE (
ECHO "%compname%",x86,"%softname%","%softver%">>"%output_file%"
)
:clrsoft
SET "softname="
SET "softver="
GOTO :EOF
Naturally, you'd need to set up your own output filename. I've also removed the psexec \\%%i and set up my machine name in q41887529.txt for testing on my machine.
Since the only difference between the queries is the node, I combined the steps and controlled them using %%z.
Clear the tempvars, then process each return line for one of the three target strings.
If it's a name, then call :report to report any accumulated data, then record the name
If it's a version, record the version and since this should now give us a pair, report it.
If it's neither, then it must be a new key, so report what we have so far.
The wart is that the version need not exist - and the final entry may be versionless, so we try reporting again to ensure any accumulated data is output.
I've revised this now and replaced the original.
It will report the machine name extracted from the file and I believe that the often-missing version number has been fixed - the order of name and version are unpredictable, so the report is triggered with the data accumulated between instances of HKEY_ and at the very end.

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

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

Resources