Getting PID from running bat script - batch-file

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

Related

How to escape spaces while Set a parameter in Bat 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

count number of (pid) variables in an array?

I'm trying to count the number of ruby scripts I am running in a batch script.
I can get the script to list the numbers, but how do I count them. Ideally, I would receive an alert when the number of PIDs has decreased.
Thank you!
#Echo off & SetLocal EnableDelayedExpansion
set "RUBY="
for /f "tokens=2" %%A in ('tasklist ^| findstr /i "ruby.exe" 2^>NUL') do
#Set "PID=!PID!,%%A"
if defined PID Echo cmd.exe has PID(s) %PID:~1%
echo ${#PID[#]}
pause
If you just want to know how many instances of a program is running then use the count functionality of the FIND command.
FOR /F "delims=" %%G IN ('tasklist ^|find /I /C "ruby.exe"') do set count=%%G

How to Kill Running Process from a specific folder via Batch File

I am writing an uninstaller batch file and it occasionally fails to delete folders because of running process. Is there a way to kill all running process that reside in a particular folder. Keep in mind that there could be multiple process running from subfolders within the main. So I think it needs to search the running processes and forcefully and silently kill all that reside within "C:\Program Files\PTC" or a subfolder within.
I do know how to kill off a specific process using the "Taskkill" command, but searching for all process running within a folder and killing them all off is a little over my head.
Thanks for the help in advance.
Bill
Batch isn't suited to this as you can see by the gobblygook in previous answer. The line to terminate is commented out ' character.
This is VBS.
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
' If Instr(objItem.ExecutablePath, "C:\Program Files") > 0 Then objItem.terminate
If Instr(objItem.ExecutablePath, "C:\Program Files") > 0 Then msgbox objItem.name
Next
You can use WMIC to get help as they use the same objects.
wmic /?
wmic process /?
wmic process call /?
wmic process get /?
The way with you'll get the most comprehensive information about a process with batch file will be the WMIC command. Though it does not contain a working directory so probably you'll have to orient yourself by the command line.
Check the comments in the script bellow.First replace the workdir variable with your desired path and if the process looks ok uncomment the last line.You can precise:
#echo off
:: Put the work dir here
set "workdir=C:\Windows\system32"
set "workdir=%workdir:\=\\%"
setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
wmic process where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"' get CommandLine^,ProcessId /format:value
`) do (
for /f "tokens=* delims=" %%# in ("%%a") do (
if "%%#" neq "" (
echo %%#
set "%%#"
)
)
)
rem if the echoed process looks ok unocment line bellow
rem taskkill /pid %ProcessID% /f
the %% is the wildcard in the wmic query so you can precise the selection more. Pay attention that the second part is not like (and is just for example). Here's more about WQL
I think PowerShell is a much easier way to do this task.
You would start with the cmdlet get-process
get-process | select ProcessName, Path
This would display the name and the path of where the process is running from.
Then you would make sure none of the processes are running from the path you care about. If they are running you would use stop-process -id $id -force
Below you will find improved version of script created by npocmaka in post above. You can also download this script from closeapps.cmd
#echo off
if "%1"=="" goto help
:: Put the work dir here
set "workdir=%1
set "workdir=%workdir:\=\\%"
setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
wmic process where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"' get CommandLine^,ProcessId /format:value
`) do (
for /f "tokens=* delims=" %%# in ("%%a") do (
if "%%#" neq "" (
set "%%#"
SET var="%%#"
SET searchVal=ProcessId
SET var|FINDSTR /b "var="|FINDSTR /i %searchVal% >nul
IF ERRORLEVEL 1 (echo.) ELSE (taskkill /pid !ProcessId! /f)
)
)
)
goto end
:help
echo ********************
echo * Example of Usage *
echo ********************
echo.
echo =============================================
echo closeapp \\server\path\test
echo.
:end
This works for me...
See example below
FOR /F "delims=" %%G in ('FORFILES /P "%ProgramFiles%\Microsoft VS Code" /M *.EXE /S') DO (
TASKKILL /F /IM %%G /T
)
Essentially this kill all processes within the root and subfolders of %ProgramFiles%\Microsoft VS Code

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 Path Expansion Batch Script

I am having a problem with Windows path expansion using a batch file where the variable contains a string from the Windows registry. See script below. I have tried multiple methods but I must be missing something simple.
#echo off
setlocal enabledelayedexpansion
for /f "tokens=2*" %%a in ('reg.exe query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services" /t REG_EXPAND_SZ /f ServiceDll /s ^| grep.exe -ia "REG_EXPAND_SZ" ') do (
set registry_value2=%%b
call :regmerge
)
goto :endofscript
:regmerge
echo !registry_value2!
goto :eof
:endofscript
endlocal
Replace
set registry_value2=%%b
with
call set "registry_value2=%%b"
and remove the call to regmerge. The call will force the parser to do a second pass and replace the environment variables references.
Here is a possible solution with the use of findstr and storing the intermediate result in a temp file.
#echo off
rem tempfile
set tf=regfind.tmp
rem reg query output pipe into findstr and redirect to temnpfile
reg.exe query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services" /t REG_EXPAND_SZ /v ServiceDll /s | findstr /C:SystemRoot > %tf%
rem iterate over each line in temp file and call merge
for /F "tokens=3*" %%a in (%tf%) do call :merge %%a
rem delete tempfile
del /q %tf%
goto :eof
:merge
rem SystemRoot is exapanded now...
echo %1
goto :eof

Resources