Batch: ECHO is on always when trying to output variable content - for-loop

I'm always getting the message "Echo is on" when trying to run the script..
setlocal ENABLEEXTENSIONS
C:
cd ..
cd ..
reg query "HKLM\SYSTEM\CurrentControlSet\Services" | findstr /b "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DummyService" > "C:\servicePaths.txt"
FOR /f "delims=" %%g IN (servicePaths.txt) do (
set KEY_NAME="%%g"
set VALUE_NAME=ImagePath
FOR /F "tokens=1-3" %%A IN ('REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul') DO (
set ValueValue=%%C
)
echo %ValueValue%
pause
)
Could any batch-guru please help me? I know that it has something to do with the cascaded for-loops, but I cannot find the solutions - no clue anymore after 3 hours try&error.

It's a problem of expanding the %ValueValue%, as this happens when the complete parenthesis block is parsed.
Not when it is executed, but at parse time the ValueValue variable is empty, so you get only echo which will print echo is on.
Simply change it to delayed expansion
#echo off
setlocal EnableDelayedExpansion
C:
cd ..
cd ..
set VALUE_NAME=ImagePath
reg query "HKLM\SYSTEM\CurrentControlSet\Services" | findstr /b "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DummyService" > "C:\servicePaths.txt"
FOR /f "delims=" %%g IN (servicePaths.txt) do (
set "KEY_NAME=%%g"
FOR /F "tokens=1-3" %%A IN ('REG QUERY !KEY_NAME! /v !VALUE_NAME! 2^>nul') DO (
set ValueValue=%%C
)
echo !ValueValue!
pause
)

Related

Batch "For" loop outputs in two lines instead of one in TXT

I want this following for-loop to output the findings of these two searches in one line in the All_Metadata.txt
for %%a in (*.txt) do (
findstr /B "589" %%a
findstr /X /C:"1 1,96 " %%a
) >> All_Metadata.txt
This For-Loop output looks like this:
58998545
1 1,96
Instead of (this is what it should look like):
58998545 1 1,96
Operating System: Windows 10
Capture the output of the both findstr commands into variables with for /f loops and echo them together (no need for a variable with the second one; just use the for variable):
#echo off
setlocal ENABLEDELAYEDEXPANSION
for %%a in (*.txt) do (
set "b="
set "c="
for /f "delims=" %%b in ('findstr /B "589" "%%a"') do set "b=%%b"
for /f "delims=" %%c in ('findstr /i /X /C:"1 1,96 " "%%a"') do set "c=%%c"
echo(!b! !c!
)
Another way is, to use the set /p trick to write the first findstr result without a line feed and just add the result from the second findstr (doesn't need delayed expansion):
#echo off
setlocal
for %%a in (*.txt) do (
set "b="
for /f "delims=" %%b in ('findstr /B "589" "%%a"') do <nul set /p "=%%b "
findstr /i /X /C:"1 1,96 " "%%a"
)

Single line nested loop

I am experimenting with a single line cmd /c to get an inner loop without branching. (Actually i have the showLines routine which performs the loop.) I know its worst for performance but i want to know if its possible to get it run without quotes. Currently it raises "%G was unexpected at this time" error. So, it needs some correct escaping or expansion of variables.
#echo off
setlocal enableDelayedExpansion
set "param=%~1"
netstat -aonb | findstr /n $ > tmpFile_Content
for /F "tokens=*" %%A in ('type tmpFile_Content ^| findstr /r /c:"%param%" /i') do (
SET line=%%A
for /F "tokens=1 delims=:" %%I in ("!line!") DO (
set /a LineNum=%%I
rem set /a NextLineNum=LineNum+1
)
set /a lineNum=!LineNum!-1
if !lineNum!==0 ( set param="tokens=*" ) else ( set param="tokens=* skip=!lineNum!" )
rem FOLLOWING WORKS FINE in quotes
cmd /q /v:on /c "#echo off && setlocal enableDelayedExpansion && set cnt=2 && for /F %%param%% %%B in (tmpFile_Content) do ( echo %%B && set /a cnt-=1 >nul && if ^!cnt^!==0 exit /b )"
rem Following does not work even though cmd should take the rest of arguments after /c
cmd /q /v:on /c setlocal enableDelayedExpansion && FOR /F "tokens=*" %%C IN ('echo !param!') DO ( for /F %%C %%G in (tmpFile_Content) do ( echo %%G && set /a cnt-^=1 >nul && if ^!cnt^!==0 exit /b ))
rem call :showLines !LineNum!
)
del tmpFile_Content
goto :eof
:showLines
set /a lineNum=%1-1
set cnt=2
for /F "tokens=* skip=%lineNum%" %%B in (tmpFile_Content) do (
echo %%B
set /a cnt-=1
if !cnt!==0 goto exitLoop
)
:exitLoop
exit /b
to construct for loops with variable parameters, you essentially need to define and execute them as a macro. Eg:
#Echo Off & Setlocal ENABLEdelayedExpasnion
Set param="tokens=* delims="
Set "test=string line"
Set For=For /F %param% %%G in ("^!test^!") Do echo %%G
%For%
Of course you could go even further, and build the entire for loop with another for loop macro on the fly.
UPDATE:
Method for defining conditional concatenation of commands now exampled
Syntax simplified to allow the same usage form for regular expansion and within codeblocks by having the constructor macro call a subroutine to expand the new for loop once it's constructed.
delayed concatenation variable usage simplified to avoid the escaping requirement
#Echo off
::: { Macro Definition
Setlocal DisabledelayedExpansion
(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)
::: [ For Loop Constructor macro. ] For advanced programmers who need to use dynamic for loop options during code blocks.
::: - usage: %n.For%{For loop options}{variable set}{For Metavariable}{commands to execute}
::: - use delayed !and! variable to construct concatenated commands in the new for loop.
Set n.For=For %%n in (1 2) Do If %%n==2 (%\n%
Set FOR=%\n%
For /F "tokens=1,2,3,4 Delims={}" %%1 in ("!mac.in!") Do (%\n%
Set "FOR=For /F %%1 %%3 in ("!%%2!") Do (%%~4)"%\n%
)%\n%
Call :Exc.For%\n%
)Else Set mac.in=
Set "and.=&&"
Set "and=!and.!"
::: } End macro definition.
Setlocal EnableDelayedExpansion& rem // required to expand n.For constructor macro
::: - Usage examples:
Set "example=is a string line"
%n.For%{"tokens=* delims="}{example}{%%G}{Echo/%%~G}
%n.For%{"tokens=1,2,3,4 delims= "}{example}{%%G}{"Echo/%%~J %%~G %%~H %%~I !and! Echo/%%~I %%~G %%~H %%~J"}
Set "example2=Code block example"
For %%a in (1 2 3) do (
%n.For%{"Tokens=%%a Delims= "}{example2}{%%I}{"For /L %%# in (1 1 4) Do (Set %%I[%%#]=%%a%%#) !and! Set %%I[%%#]"}
)
Pause > Nul
Goto :EOF
:Exc.For
%FOR%
Exit /B
Example output:
is a string line
line is a string
string is a line
Code[1]=11
Code[2]=12
Code[3]=13
Code[4]=14
block[1]=21
block[2]=22
block[3]=23
block[4]=24
example[1]=31
example[2]=32
example[3]=33
example[4]=34
Finally, i came up with following to execute code given in string for anyone interested experimentally and may be for some insight about escaping and expansion.
I use macro instead of cmd which will be much more faster i think(not sure because its said that "call" also causes launch of cmd).
So, it is a simple one-liner without a lot of extra code. But things easily become complicated and when extra escaping and special characters used then #T3RR0R's macro routine would be a necessity.
#echo off
setlocal EnableDelayedExpansion
set "param=%~1"
netstat -aonb | findstr /n $ > tmpFile_Content
for /F "tokens=*" %%A in ('type tmpFile_Content ^| findstr /r /c:"%param%" /i') do (
SET line=%%A
for /F "tokens=1 delims=:" %%I in ("!line!") DO (
set /a LineNum=%%I
rem set /a NextLineNum=LineNum+1
)
set /a lineNum=!LineNum!-1
rem CORRECT QUOTING
if !lineNum!==0 ( set "param="tokens=*"" ) else ( set "param="tokens=* skip=!lineNum!"" )
rem FOLLOWING WORKS FINE in quotes
rem cmd /q /v:on /c "set cnt=2 && for /F ^!param^! %%B in (tmpFile_Content) do ( echo %%B && set /a cnt-=1 >nul && if ^!cnt^!==0 exit /b )"
rem For reading !cnt! use !x!cnt!x!.
rem Only one extra variable used, and in routine its replaced with !(exclamation) for our "cnt" variable.
set "x=^!x^!"
call :ExecCode "set cnt=2 && for /F ^!param^! %%%%B in (tmpFile_Content) do (echo %%%%B && set /a cnt=!x!cnt!x!-1 >nul && if !x!cnt!x!==0 (exit /b) )"
rem call :showLines !LineNum!
)
del tmpFile_Content
goto :eof
:ExecCode
setlocal
rem Replace with exclamation for variable
set "x=^!"
set "s=%~1"
%s%
endlocal
exit /b
:showLines
set /a lineNum=%1-1
set cnt=2
for /F "tokens=* skip=%lineNum%" %%B in (tmpFile_Content) do (
echo %%B
set /a cnt-=1
if !cnt!==0 goto exitLoop
)
:exitLoop
exit /b

How to find string and then divide the token while reading the file line by line using batch script

I have tried to do like this
Inputfile contains the file which has to be read
for /F "tokens=* delims=" %%A in (%INPUTFILE%) do (
SET my_line=%%A
SET my_line=%my_line:#define ACCEL_PRESENT%
findstr /C:"define ACCEL_PRESENT"
if %errorlevel%==0 ( SET my_line=%%A
call :parse_it
)
)
:parse_it
for /F "usebackq tokens=1-6 delims= " %%1 in ('%my_line%') do (
echo %%3 > t.txt
)
I am getting nothing from the above code.Can someone help me with the desired results
Here is one possible solution:
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=* delims=" %%A in (%INPUTFILE%) do (
set "my_line=%%A"
set "my_line=!my_line:#define ACCEL_PRESENT=!"
echo !my_line! | findstr /C:"define ACCEL_PRESENT"
IF !errorlevel! EQU 0 ( SET "my_line=%%A" && call:parse_it )
)
:parse_it
for /F "usebackq tokens=1-6 delims= " %%A in ("%my_line%") do echo %%C > t.txt
rem exit /b
I hope you wanted to delete string #define ACCEL_PRESENT.
Also, say me if %my_line% is a command (I don't think so, so I removed single-quotes and I added double-quotes).
Better to use letter variables in for loops!

Using FOR Loop and SC Query in CMD Script

Suppose this instruction:
C:\>SC query state= all | find /I "adobe"
The result is:
SERVICE_NAME: AdobeARMservice
DISPLAY_NAME: Adobe Acrobat Update Service
Now I want to obtain the exact argument in this case is "AdobeARMservice"
Here my Script TestLineArgument.bat:
#echo off
cls
REM
REM for /f "delims=" %%# in ('SC query state= all ^| find /I "adobe"') do ( IS NOT WORKING
REM
set "SCQueryState=SC query state ^= all"
set "QueryAdobe=%SCQueryState%^^^| find /I ^"adobe^""
for /f "delims=" %%# in ("%QueryAdobe%") do (
set "THERSERVICE_NAME=%%#"
echo %%#
goto :END_FORSCQUERY
)
:END_FORSCQUERY
REM show the Line "SERVICE_NAME: AdobeARMservice"
echo THERSERVICE_NAME:%THERSERVICE_NAME%
FOR /f "tokens=2" %%# IN ("%THERSERVICE_NAME%") DO (
set "THESERVICE=%%#"
)
REM show the second part "AdobeARMservice"
echo THESERVICE:%THESERVICE%
My Script is not working, I don't know how use FOR with SC Command
Some clue?
#echo off
setlocal enableextensions disabledelayedexpansion
rem Initialize variables
set "serviceName="
set "displayName="
rem Execute the query and retrieve all the SERVICE_NAME lines and
rem the line with the desired display name
for /f "tokens=1,*" %%a in ('
sc query state^= all ^| findstr /i /l /c:"SERVICE_NAME" /c:"Adobe"
') do if not defined displayName if "%%a"=="SERVICE_NAME:" (
set "serviceName=%%b"
) else set "displayName=%%b"
rem Show retrieved data
if defined displayName (
echo %serviceName%
echo %displayName%
) else echo Not found
This method does not work in the manner you were trying to implement, as #MCND answer does, but if "AdobeARMservice" is only returned by sc query state when it is running, this may be useful.
It simply looks for the string "AdobeARMservice" and sets THESERVICE var to the result: If "AdobeARMservice" not found, THESERVICE remains empty. If found it gets value=AdobeARMservice
#echo off
Set "THESERVICE="
For /f %%A in ('sc query state^= all ^| find /i "AdobeARMservice"') do set THESERVICE=%%A
If "%THESERVICE%"=="" echo AdobeARMservice not found
If NOT "%THESERVICE%"=="" echo THESERVICE: %THESERVICE%
pause
My problem was simply...
#echo off
set "SERVICE=Adobe"
for /f "delims=" %%s in ('sc query state^= all ^| find /I "%SERVICE%"') do (
for /f "tokens=2" %%# in ("%%s") do (
echo THESERVICE:%%#
)
)
I tryng to avoid to change the code according to version something like : "Adobe3.2_1" or "Adobe3.2_5" or "Adobe4.5", this snippet of code only...

Syntax issue in batch

I have been working on this script for a little and I am new to writing batch files. I know my syntaxs is wrong and need some help.
#echo off
setlocal enabledelayedexpansion
set "ports=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports"
for /f %%I in ( 'reg query "%ports%"')
do (
echo %%I | findstr /i "c:\\convertdoc\\output\\silentprinttemp\\.*\.ps" >NUL
IF ERRORLEVEL 1 reg delete "%ports%" /v "%%I" /f
)
#echo off
setlocal
set "ports=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports"
for /f %%I in (
'reg query "%ports%"'
) do (
echo %%I | findstr /i "c:\\convertdoc\\output\\silentprinttemp\\.*\.ps" >NUL
IF ERRORLEVEL 1 reg delete "%ports%" /v "%%I" /f
)
As the comments also point out, cmd wants "do" on the same line as the closing parenthesis of the previous expression. You're not using delayed expansion. It's not an error, but I see no reason to turn it on.
#echo off
setlocal
set "ports=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports"
for /f %%I in ( 'reg query "%ports%"' ) do (
echo %%I | findstr /i "c:\\convertdoc\\output\\silentprinttemp\\.*\.ps" >NUL
IF ERRORLEVEL 1 reg delete "%ports%" /v "%%I" /f
)
Curiously, this experiment worked:
FOR /F %%i IN (
'dir /b'
) DO (
#ECHO %%i
)

Resources