How to kill specific VBScript using batch file? - windows

How to kill specific VBScript using batch file?
#echo off
set vbs="%temp%\dummy.vbs"
for /f "usebackq tokens=2" %%s in (`WMIC path Win32_Process where 'name="wscript.exe"' get commandline,processid | findstr /i /c:"%vbs%"`) do (
taskkill /f /fi "pid eq %%s"
)
I also tried the code below but it seems that commandline like is not working.
WMIC path Win32_Process where "name='wscript.exe' and commandline like %vbs%" get processid
Thanks in advance!

Incorporated items in the comments and escaped special characters with ^.
#echo off
set "vbs=%temp%\dummy.vbs"
for /f "usebackq tokens=3" %%s in (
`WMIC process where "name='wscript.exe'" get commandline^,processid ^| findstr /i /c:"%%vbs%%"`
) do (
taskkill /f /fi "pid eq %%s"
)

Related

Batch error "( unexpected" if statement nested inside for loop

I wrote this small script to kill Spotify whenever the title of the window is "Advertisement". For now, it just looks for the spotify.exe process and, if the name of the window matches, kills it (next step is executing it every second). However, I get an error every time I execute it, telling me that there's an unexpected ( in IF /i "%A:~0,4" (, but such statement is not in my code: it seems like Windows modifies IF /i "%%A:~0,4%"=="PID:" ( before executing it.
Here's the script:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
tasklist /fi "imagename eq spotify.exe" /fo list /v > tmp.txt
FOR /F "usebackq tokens=*" %%A IN ("tmp.txt") DO (
SET test=%%A
echo %%A
IF /i "%%A:~0,4%"=="PID:" (
SET "pid=%%A:PID: =%"
echo %pid%
)
IF /i "%%A:~0,13%"=="Window Title:" (
SET "wintitle=%%A:Window Title: =%"
echo %wintitle%
)
IF "%wintitle%"=="Advertisement" (
taskkill /F /PID %pid%
)
)
PAUSE
Error message (with echo on):
C:\Users\marco\Desktop>antispotify.bat
C:\Users\marco\Desktop>tasklist /fi "imagename eq spotify.exe" /fo list /v 1>tmp.txt
( was unexpected at this time.
C:\Users\marco\Desktop> IF /i "%A:~0,4" (
Does anyone know what's wrong with my code?
The task to force a real kill of Spotify process running for advertisement can be done also by using following batch file without using delayed expansion.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\tasklist.exe /FI "imagename eq spotify.exe" /FO LIST /V 2^>nul') do (
if /I "%%~I" == "PID" (
for /F %%K in ("%%~J") do set "ProcessIdentifier=%%~K"
) else if /I "%%~I" == "Window Title" (
for /F "tokens=*" %%K in ("%%~J") do if /I "%%~K" == "Advertisement" call %SystemRoot%\System32\taskkill.exe /F /PID %%ProcessIdentifier%%
)
)
endlocal
The same code with using delayed environment variable expansion:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\tasklist.exe /FI "imagename eq spotify.exe" /FO LIST /V 2^>nul') do (
if /I "%%~I" == "PID" (
for /F %%K in ("%%~J") do set "ProcessIdentifier=%%~K"
) else if /I "%%~I" == "Window Title" (
for /F "tokens=*" %%K in ("%%~J") do if /I "%%~K" == "Advertisement" %SystemRoot%\System32\taskkill.exe /F /PID !ProcessIdentifier!
)
)
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.
call /?
echo /?
endlocal /?
for /?
if /?
setlocal /?
taskkill /?
tasklist /?
See also: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
As noted in the comments, substring manipulation doesn't work on for variables (%%a type). Instead, you need an ordinary variable and of course delayed expansion.
But may I suggest another approach:
#ECHO OFF
SETLOCAL
for /f "tokens=2,9 delims=," %%a in ('tasklist /fi "imagename eq notepad.exe" /fo csv /v /nh') do (
set "pid=%%~a"
set "wintitle=%%~b"
)
set pid
set wintitle
IF "%wintitle%"=="Advertisement" taskkill /F /PID %pid%
Here we use the command directly with the for loop instead of using a temporary file. Besides that, we change the output format to csv (easier to parse) with no header line ( /nh)
( I used notepad.exe, because I don't have spotify, but that's easy to adapt)

Collect each service's display name and status

I want to get list of services with their display name and their status.
This is what I have tried:
for /f "tokens=2" %s in ('SC query state^= all ^| find "DISPLAY_NAME"') do #(for /f "tokens=4" %t in ('SC query %s ^| find "STATE"') do #echo %s is %t)
But this returns only limited services such as disk, etc.
This is a perfect task for the built-in WMI command line executable, WMIC.exe.
From the cmd.exe prompt:
For /F "Skip=1 Delims=" %A In ('"WMIC Service Get DisplayName, Name, State"') Do #For /F "Delims=" %B In ("%A") Do #Echo(%B
From a batch file:
#For /F "Skip=1 Delims=" %%A In ('"WMIC Service Get DisplayName, Name, State"'
) Do #For /F "Delims=" %%B In ("%%A") Do #Echo(%%B
#Pause
Try getting help from powershell directly in your batch file, like this for example (save as .bat and run it). In the example i type it to the screen and give you ALL services, RUNNING ONLY, and STOPPED ONLY but you could do basically what you want with the content of that txt file (search it with a loop, save a part to a variable, etc.).
#echo off&cls
pushd %~dp0
echo.
echo List ALL services
pause
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "powershell Get-Service | Out-File services.txt"
type services.txt
echo.
echo List services that are RUNNING only
pause
find "Running" services.txt
echo.
echo List services that are STOPPED only
pause
find "Stopped" services.txt
pause
:cleanup
del /f services.txt

Save the result of a command in variable, Windows batch

I am trying to write a batch script that saves the result of a command in a variable. so I can use it later.
For example I am tryin to run this on the script:
sc queryex "Service" |find /i "pid"
but I want to save this result in a variable.
set PIDRS=sc queryex "Themes" |find /i "pid"
ECHO "%PIDRS%
Any Ideas?
for /f "tokens=* delims=" %%# in ('sc queryex "Themes" ^|find /i "pid"') do set "PIDRS=%%#"
echo %PIDRS%
This will set the entire line to PIDRS
here's how to get only the pid:
#echo off
set "rspid="
for /f "skip=9 tokens=2 delims=:" %%# in ('sc queryex "Themes"') do (
if not defined rspid set /a rspid=%%#
)
the second does not use additional FIND which in theory should make it faster.

Get the PID of a Windows service by the name of the service

Is there a way of getting the PID of a windows service with a command in a batch script by just knowing the name of the service?
Try the following code:
FOR /F "tokens=3" %%A IN ('sc queryex %serviceName% ^| findstr PID') DO (SET pid=%%A)
IF "!pid!" NEQ "0" (
taskkill /F /PID !pid!
)
It's much easier to just do taskkill /f /fi "SERVICES eq <service_short_name>"
#echo off
for /f "tokens= delims=" %%# in ('
wmic service where "name='Service'" get ProcessId /format:value
') do (
for /f "tokens=* delims=" %%$ in ("%%#") do set "%%$"
)
taskkill /pid %ProcessId% /f

How to get PID of process just started from within a batch file?

In Windows batch scripting there is start command which starts a new process.
Is it possible to get PID of the process just started?
This is an old post but I think that it worth to share the following 'easy to use' solution which works fine nowadays on Windows.
Start multiple processes in parallel:
start "<window title>" <command will be executed>
Example:
start "service1" mvn clean spring-boot:run
start "service2" mvn clean spring-boot:run
Obtain the PID of the processes (optional):
tasklist /V /FI "WindowTitle eq service1*"
tasklist /V /FI "WindowTitle eq service2*"
Kill the processes:
taskkill /FI "WindowTitle eq service1*" /T /F
taskkill /FI "WindowTitle eq service2*" /T /F
You can in batch but not directly per say. You need to either parse the output of tasklist.exe or use wmic.exe. Both require you to know what you just started which of course you will.
Using tasklist.exe:
for /F "TOKENS=1,2,*" %a in ('tasklist /FI "IMAGENAME eq powershell.exe"') do set MyPID=%b
echo %MyPID%
To use this in a batch script double up the percent signs.
Using wmic.exe:
for /f "TOKENS=1" %a in ('wmic PROCESS where "Name='powershell.exe'" get ProcessID ^| findstr [0-9]') do set MyPID=%a
echo %MyPID%
If there are processes already running with the same name, you first need to get a list of the current pids, than start your local process(es) and then check the pids again. Here is a sample code that starts 3 process and kills them at the end (specifically the ones started locally):
#echo off
set PROCESSNAME=notepad.exe
::First save current pids with the wanted process name
setlocal EnableExtensions EnableDelayedExpansion
set "RETPIDS="
set "OLDPIDS=p"
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (set "OLDPIDS=!OLDPIDS!%%ap")
::Spawn new process(es)
start %PROCESSNAME%
start %PROCESSNAME%
start %PROCESSNAME%
::Check and find processes missing in the old pid list
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (
if "!OLDPIDS:p%%ap=zz!"=="%OLDPIDS%" (set "RETPIDS=/PID %%a !RETPIDS!")
)
::Kill the new threads (but no other)
taskkill %RETPIDS% /T > NUL 2>&1
endlocal
you can try with
wmic process call create "notepad"
which will return the pid of the created process.
Processing this with FOR
setlocal
set "ReturnValue="
set "ProcessId="
for /f "eol=} skip=5 tokens=1,2 delims=;= " %%a in ('wmic process call create "notepad"') do (
set "%%a=%%b"
)
echo %ReturnValue%
echo %ProcessId%
endlocal
PowerShell can be used for this:
powershell -executionPolicy bypass -command "& {$process = start-process $args[0] -passthru -argumentlist $args[1..($args.length-1)]; exit $process.id}" notepad test.txt
echo Process ID of new process: %errorlevel%
This is the code that i use to get a PID
for /f "tokens=2 delims=," %%a in ('tasklist /FO CSV ^| findstr /I /C:"entertheprocess.here"') do (
echo PID:%%a
)
#ECHO OFF
SETLOCAL EnableDelayedExpansion EnableExtensions
::
::weil es mehrere Sessions für UltraCompare gleichzeitig geben kann, es wird hier die
::neueste Instanz (soeben gestartet) ermittelt, um später mit ProcessId diese Instanz
::aktivieren zu können...
::
set "CreationDate="
set /A "ProcessIdUltraCompare=0"
::
set /A "lineno=0"
FOR /F %%T IN ('Wmic process where^(Name^="uc.exe"^) get CreationDate^|sort /r') DO (
set /A lineno+=1
rem echo %%T
rem echo !lineno!
if !lineno! equ 2 (
rem ECHO %%T
set CreationDate=%%T
rem echo !CreationDate!
set /A "lineno=0"
FOR /F %%P IN ('Wmic process where^(CreationDate^="!CreationDate!"^) get ProcessId') DO (
set /A lineno+=1
rem echo %%P
if !lineno! equ 2 (
set "ProcessIdUltraCompare=%%P"
rem echo ProcessIdUltraCompare=!ProcessIdUltraCompare!
goto :l_pid_uc_got
)
)
)
)
:l_pid_uc_got
echo ProcessIdUltraCompare=!ProcessIdUltraCompare!
PAUSE

Resources