How to escape spaces while Set a parameter in Bat file - batch-file

I'm trying to do this:
#echo off
Set ^"Processes=Sample.exe ^
The Sample Program.exe^"
But The Sample Program.exe acting as three separate files The Sample and Program.exe.
What is the procedure to escape the spaces?
Full code:
for %%a in (%Processes%) Do (
for /f %%b in ('tasklist /NH /FI "imagename eq %%a"') Do (
if [%%b]==[%%a] (
echo %%b is running
Color 0C
echo Killing %%b ...
Taskkill /f /im "%%b"
) else (
Color 0A
echo %%a is not running
)
)
)
pause & exit
Something along this line?
for /F "tokens=1* delims=," %%b

A simple demonstration code for what I think you want to achieve is:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set Processes="cmd.exe Windows Command Processor" "cscript.exe Console Based Script Host"
for %%G in (%Processes%) do for /F "eol=| tokens=1*" %%H in (%%G) do (
echo File name is: %%H
echo Process name: %%I
)
endlocal
The output of this batch file on execution is:
File name is: cmd.exe
Process name: Windows Command Processor
File name is: cscript.exe
Process name: Console Based Script Host
So the environment variable Processes is defined with multiple strings enclosed in double quotes. Each string has first the file name of an executable without path and separated by a space (could be also a different character) the process name or whatever is needed to be associated with the executable file name which should not contain ? or *.
The outer FOR loop assigns one after the other a string enclosed in double quotes to the specified loop variable G.
The inner FOR loop splits up the string assigned currently to loop variable G into two substrings and assigns the first normal space/horizontal tab delimited string to specified loop variable H and everything else after one or more spaces/tabs to next but one loop variable I.
The executable file name assigned to H and the associated string assigned to I can be used for whatever purpose in the command block of the inner FOR loop.
This method applied to what the batch file should do:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set Processes="notepad.exe Windows Notpad" "cscript.exe Console Based Script Host"
for %%G in (%Processes%) do for /F "eol=| tokens=1*" %%H in (%%G) do (
%SystemRoot%\System32\tasklist.exe /NH /FI "imagename eq %%H" 2>nul | %SystemRoot%\System32\find.exe /I "%%H" >nul
if not errorlevel 1 (
echo %%I is running.
color 0C
echo Terminating %%I ...
%SystemRoot%\System32\taskkill.exe /IM "%%H" >nul
) else (
color 0A
echo %%I is not running.
)
)
color
endlocal
The option /F to force a brutal kill of the running process by the operating system is removed from this code. The most applications gracefully terminate itself on TASKKILL sending the WM_CLOSE message to the running application.
Please note that closing all instances of script interpreters like cmd.exe, cscript.exe, wscript.exe, powershell.exe as done by the TASKKILL with just image name passed as argument is in general not good. For example the cmd.exe instance currently processing the batch file would be terminated also on using this batch code to terminate a cmd.exe running with a different console window parallel.
Example for the unusual cases of executable file names with one or more spaces with using | as delimiter between file name and associated string which no file name can contain ever:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set Processes="notepad.exe|Windows Notpad" "cscript.exe|Console Based Script Host" "show time.exe|Show Time Information"
for %%G in (%Processes%) do for /F "eol=| tokens=1* delims=|" %%H in (%%G) do (
%SystemRoot%\System32\tasklist.exe /NH /FI "imagename eq %%H" 2>nul | %SystemRoot%\System32\find.exe /I "%%H" >nul
if not errorlevel 1 (
echo %%I is running.
color 0C
echo Terminating %%I ...
%SystemRoot%\System32\taskkill.exe /IM "%%H" >nul
) else (
color 0A
echo %%I is not running.
)
)
color
endlocal
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
find /?
for /?
setlocal /?
taskkill /?
tasklist /?

Example based upon my comment:
Set ^"Processes="Sample.exe"^
"The Sample Program.exe"^"
For %%G In (%Processes%) Do Echo %%G
Pause
Obviously when using %%G in your /Filter, you'd just remove those doublequotes, i.e. %SystemRoot%\System32\tasklist.exe /NH /Fi "ImageName Eq %%~G"
Please note that the leading space before any line which begins with a doublequote is required

Related

Getting PID from running bat script

Hi i'm trying to find a way to get my own PID from a bat script.
I found this:
title=mycmd
tasklist /v /fo csv | findstr /i "mycmd"
that outputs:
"cmd.exe","15084","RDP-Tcp#5","2","2,768 K","Running","MEDIASERVER\Administrator
","0:00:00","Administrator: =mycmd"
how would I get the PID number into a variable in my bat script?
any help would be appreciated.
#echo off
setlocal enableextensions disabledelayedexpansion
rem Prepare a temporary file reference where to send the wmic output
for %%t in ("%temp%\%~nx0.%random%%random%%random%%random%%random%.tmp") do > "%%~ft" (
rem Call wmic to retrieve its own parent process ID, that is, our cmd instance
wmic process where "name='wmic.exe' and commandline like '%%_%random%%random%%random%_%%'" get parentprocessid
rem Read the PID from the generated temporary file
for /f "skip=1" %%a in ('type "%%~ft"') do set "processID=%%a"
rem And remove the temporary file
) & 2>nul del /q "%%~ft"
echo %processID%
try with getcmdpid , thus you will not need to change the title:
call getCmdPID.bat
echo %errorlevel%
to do it with tasklist you'll need for loop to process the output:
title mycmd
for /f "tokens=2 delims=," %%a in (
'tasklist /v /fo csv ^| findstr /i "mycmd"'
) do (
set "mypid=%%~a"
)
echo %mypid%
check also this thread:
http://www.dostips.com/forum/viewtopic.php?t=6133

cmd - know if have multiple console processes with same name and taskkill them

I am using in cmd: tasklist /FI "session name eq console" to get list of console process es running.
I need to know if there is more than one process with same name and taskkill them
Thanks for helping
Take a look into this
Kill all processes with the same name
You need to count every image name occurrence from tasklist command output, see next batch script commented code snippet:
#ECHO OFF
SETLOCAL EnableExtensions
rem remove all variables with ? prefix (question mark)
for /F "tokens=1 delims==" %%G in ('2^>NUL set ?') do SET "%%~G="
rem count
for /F "skip=1 tokens=1 delims=," %%G in ('
tasklist /FI "SESSIONNAME eq Console" /FO csv
') do set /A "?%%~G+=1"
rem use counters
for /F "tokens=1,2 delims=?=" %%G in ('2^>NUL set ?') do (
if %%H GTR 1 (
rem next echo for debugging purposes
echo %%G process counter = %%H
if /I NOT "%%G"=="cmd.exe" (
rem taskkill command is merely displayed for debugging purposes
ECHO taskkill /IM %%G
) else (
rem needs more elaborated code to avoid killing the script itself
echo retain %%G
)
)
)
Output:
==> D:\bat\SO\37639505.bat
chrome.exe process counter = 4
taskkill /IM chrome.exe
cmd.exe process counter = 2
retain cmd.exe
iexplore.exe process counter = 3
taskkill /IM iexplore.exe
powershell_ise.exe process counter = 2
taskkill /IM powershell_ise.exe
==>

batch file setting system time with GPS

My GPS device sends on COM port the NMEA infos.
I want to extract the time info and set the system time.
In a batch I wrote:
type COM2 | find "GPRMC"
brings me the required info - but continously.
Example (first 3 lines):
$GPRMC,100211.279,V,4816.1496,N,01623.0965,E,0.00,0.00,280316,,,N*7A
$GPRMC,100212.279,V,4816.1496,N,01623.0965,E,0.00,0.00,280316,,,N*79
$GPRMC,100213.279,V,4816.1496,N,01623.0965,E,0.00,0.00,280316,,,N*78
So the next batch command is never executed, because the GPS device is sending as long as it's on.
I want to extract the second field, as in example, it is 100211 and this is 10:02:11 UTC time.
greetings
You can use this:
#echo off
for /f "tokens=2 delims=,." %%a in ('type COM2 ^| find "GPRMC"') do (
set "comTime=%%a"
goto :break
)
:break
set "comTime=%comTime:~0,2%:%comTime:~2,2%:%comTime:~4,2%
echo %comTime%
pause
This sets the time of the first line in the file to the variable comTime in the format hh:mm:ss
NOTE
This removes the .279 part of the time, to keep that part change delims=,. to delims=,
Next code snippet would take line(s) from an endless command output.
Avoid | pipe to find or findstr (read more, see Pipes and CMD.exe paragraph).
Think about delay(s) caused by …
… involved timeout commands,
… handling temporary file and
… process handling (cmd, taskkill, for).
Tested using endless ping localhost -4 -t:
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "mycommand=type COM2"
set "mytestval=$GPRMC"
rem next two lines are merely for my tests: remove them both
set "mycommand=ping localhost -4 -t"
set "mytestval=Reply"
start "bubu36260096" cmd /C ^>"%temp%\aux36260096.txt" %mycommand%
>NUL timeout /T 3 /NOBREAK
>NUL taskkill /T /F /FI "IMAGENAME eq cmd.exe" /FI "WINDOWTITLE eq bubu36260096"
>NUL timeout /T 1 /NOBREAK
rem v--- skip as many lines as you need
for /f "usebackq skip=1 tokens=1,2 delims=, " %%a in ("%temp%\aux36260096.txt") do (
rem ^--- remove this blank space in above line
if "%%a"=="%mytestval%" (
set "comTime=%%b"
goto :break
)
)
:break
rem next line for debugging purposes only
type "%temp%\aux36260096.txt"
rem set "comTime=%comTime:~0,2%:%comTime:~2,2%:%comTime:~4,2%
echo comTime ... "%comTime%"
pause

CMD Batch and 7z : Capture the progress of the extraction

I'm trying to extract something using the 7zip command line tool from a batch file
and i want just the percentage progress to appear
my code is
#echo off
for /f "tokens=3 delims=. " %%i in (
'7z x "file.rar" ^| findstr /b /r " [0-9][0-9]*\%%"'
) do (
cls
echo %%i
)
PAUSE
but all i get out is just blank during the whole extracting progress .
what went wrong?
The problem is that a FOR /F take the whole output of a command and when the command is finished it begins to iterate over the lines.
Well, this can't be used to solve your task.
But you can pipe the output to another process, in this sample I use the same batch as the second process ( %~f0 is the batch itself )
#echo off
setlocal EnableDelayedExpansion
if "%~1"==":pipe" goto %~1
7z x "file.rar" | findstr /b /r " [0-9][0-9]*\%%" | "%~f0" :pipe
echo Ready
exit /b
:pipe
set "line="
set /p line=
if defined line (
echo #### !line!
goto :pipe
)

Issue with environment variable in batch script

So, I have probably a simple question but I cannot seem to find an easy answer.
Issue: I have a file that contains a set of lines such as:
%windir%\file.exe
%windir%\file2.dll
and so forth...
What I am trying to do is echo the actual file path to a second file such that the resulting output would be something like:
C:\Windows\file.exe
C:\Windows\file2.dll
and so forth...
The actual source file could have other variables such as %programfiles% but all of them have a resulting actual path.
I am currently using a for /f loop but when I echo the variable, I just get the environment variable returned rather than the actual path to the file.
Is there a solution out there for batch scripting?
The actual script is below. Note I am all for making this more efficient as time to get the information is important.
#echo off
setlocal enabledelayedexpansion
reg.exe query "HKLM\System\CurrentControlSet\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet001\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet002\Services" >> %temp_outpath%\registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet002\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
for /f "delims=?" %%a in (registry_hklm_installed_services_tmp.txt) do (
set regkey=%%a
call :getvalue
)
goto :parsereg
:getvalue
reg.exe query "!regkey!\Parameters" /v ServiceDll > nul 2>&1 && goto regkeyexist
goto :eof
:regkeyexist
for /f "tokens=2*" %%b in ('reg.exe query "!regkey!\Parameters" /v ServiceDll') do set ImagePath=%%c
call :regag
goto :eof
:regag
echo !ImagePath! >> registry_hklm_installed_services_tmp2.txt
goto :eof
:parsereg
for /f "delims=?" %%a in (registry_hklm_installed_services_tmp2.txt) do echo %%a >> registry_hklm_installed_services_tmp3.txt
You can use the for /f command to cycle through the lines in the file like you are doing, and pass the line from the file to a subroutine inside the batch file, which will resolve it while it is being passed. Give the following:
Test.txt
%windir%\test.txt
%programfiles%\Test2.txt
This batch file will resolve the environment variables:
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%i in (Test.txt) do call :Expand "%%i"
endlocal
goto TheEnd
:Expand
set _var=%1
echo !_var:"=!
:TheEnd
This is how the output looks when you run it:
c:\>Test.bat
C:\Windows\test.txt
C:\Program Files (x86)\Test2.txt
You can redirect the result to a new text file like this:
Test.bat > NewFile.txt
Or you can modify the original Test.bat to output the modified filename under Expand instead of echoing it to the console. It is important to include the quotes around %%i ("%%i") or spaces in the resolved paths will break into multiple variables when calling Expand (e.g., %1, %2, %3, etc.). The !_var:"=! removes the quotes.
This will also expand the variables.
#echo off
for /f "delims=" %%a in (Test.txt) do call echo %%a
pause
Test.txt
%windir%\test.txt
%programfiles%\Test2.txt
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%a IN (q22726616.txt) DO (
FOR /f "delims=" %%b IN ('echo %%a') DO (
ECHO %%b
)
)
GOTO :EOF
I used a file named q22726616.txt containing your data for my testing.
[fixed following response - %%b line]

Resources