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
Related
I'm trying to write a batch file that returns the most recent file in a directory without using a for loop. I tried a lot but it's not working.
So is there a approach that we can get the most recent file without using for loop?
#echo off
cd D:\Applications
for /f "delims=" %%i in ('dir /b/a-d/od/t:c') do set RECENT="%%~nxi"
echo ..... starting jar........
start java -jar %RECENT%
echo ....jar started.....
exit 0
The execution gets stuck at start java and it does not go to next line or exit 0.
There can be used the following code using command FOR:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
cd /D "D:\Applications" 2>nul || (echo ERROR: Directory D:\Applications does not exist.& goto EndBatch)
for /F "eol=| delims=" %%i in ('dir /A-D /B /O-D /TC 2^>nul') do set "RECENT=%%i" & goto StartJava
echo WARNING: Could not find any file in directory: "%CD%"& goto EndBatch
:StartJava
if exist %SystemRoot%\System32\where.exe %SystemRoot%\System32\where.exe java.exe >nul 2>nul
if errorlevel 1 echo ERROR: Could not find java.exe. Check environment variable PATH.& goto EndBatch
echo ..... Starting jar .....
start "Running %RECENT%" java.exe -jar "%RECENT%"
if not errorlevel 1 echo ..... jar started .....
:EndBatch
if errorlevel 1 echo/& pause
endlocal
There is some error handling also added to the code.
Please note that the creation date is the date of a file on being created in the current directory. So if a file is copied from directory X to directory Y, its last modification date is not modified, but the file has a new creation date in directory Y which is newer than its last modification date.
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.
cd /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
set /?
setlocal /?
start /?
where /?
See also:
Single line with multiple commands using Windows batch file
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
I'm not sure why you don't want to use the most powerful command in cmd, but for the sake of answering your question:
dir /o-d /b "C:\my folder\*" >tmp
<tmp set /p "latest="
del tmp
echo the latest file is %latest%
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
I want to write a script to prompt user for file path and list all files found. The file path can contain wildcards. Something similar to this. But the batch script version of it. For example:
C:\Somewhere\user*\app\version-*.*\start.exe
The files might be located like this:
C:\Somewhere\user345\app\version-1.0\start.exe
C:\Somewhere\user898\app\version-1.2\start.exe
C:\Somewhere\user898\app\version-1.3\start.exe
I tried to use FOR and it turns out to be so much harder than expected because FOR does not support wildcards in the middle of a path.
Is there a way to list these files? (Maybe without using for?)
I think this recursive solution works pretty well; you may name it WCDIR.bat:
#echo off
setlocal
if "%~1" neq "" set "next=%~1" & goto next
echo Show files selected by several wild-cards
echo/
echo WCDIR wildcardPath
echo/
echo Each folder in the path may contain wild-cards
echo the last part must be a file wild-card
goto :EOF
:next
for /F "tokens=1* delims=\" %%a in ("%next%") do set "this=%%a" & set "next=%%b"
if defined next (
for /D %%a in ("%this::=:\%") do (
setlocal
cd /D "%%~a" 2>NUL
if not errorlevel 1 call :next
endlocal
)
) else (
for /F "delims=" %%a in ('dir /B /A:-D "%this%" 2^>NUL') do echo %%~Fa
)
exit /B
EDIT: I fixed a small bug in the last for /F command.
For example, the output of WCDIR.bat C:\Windows\Sys*\find*.exe command in my Windows 8.1 64-bits computer is:
C:\Windows\System32\find.exe
C:\Windows\System32\findstr.exe
C:\Windows\SysWOW64\find.exe
C:\Windows\SysWOW64\findstr.exe
You can try with the command Where /?
The WHERE command is roughly equivalent to the UNIX 'which' command. By default, the search is done in the current directory and in the PATH.
#echo off
Where /R "%programfiles%" *winrar.exe
pause
#echo off
:: Example d'input
set UserInput=*drive*
:: building the Pattern
set cmd=%Userinput%.exe
:: storage Where.exe command in a macro, the execution will be faster
set whereCmd=where.exe /r c:\windows\ %cmd%
:: execution of macro and output formatting
for /f %%a in ('%whereCmd%') do echo %%~nxa --^> %%a
pause
I currently have a batch script that I'm using to copy one large zip file from a network folder to multiple machines on the network. I need to do these copies in parallel so I've got a for loop that runs through addresses and runs start robocopy. Here's what I've got
for /F "tokens=*" %%A in (IPlist.txt) do (
start robocopy "\\networkfolder" \\%%A
)
The problem is that I need to execute an extract on all the machines I just copied to but I need to wait until the robocopies have finished. I can't use start /wait in the for loop since that destroys the parallel copy. Is there a way I can force the script to wait until all the robocopies have finished? or maybe an alternate solution?
FYI: I cannot extract on the network folder first since the zip is a lot of little files and severely slows the transfer rate. It needs to be one big file when copying over the network.
setlocal EnableDelayedExpansion
set number=0
for /F "tokens=*" %%A in (IPlist.txt) do (
set /A number+=1
echo Flag > roboRunning.!number!
start robocopy "\\networkfolder" \\%%A ^& del roboRunning.!number!
)
:wait
if exist roboRunning.* goto wait
echo All robocopy processes have finished here
Here's some code I had lying around (syntax for inside a batch file):
SETLOCAL ENABLEDELAYEDEXPANSION
set robocopycount=0
:loop
for /F "usebackq" %%e IN (`tasklist /FI "IMAGENAME eq robocopy.exe"`) do if %%e==robocopy.exe set /A robocopycount=!robocopycount!+1
if %robocopycount% GEQ 1 goto continue
rem goto loop
:continue
This actually counts the number of executables running at once but it could easily be adapted to just check for existence. (In the case of this code it was checking to ensure that a certain number were running.)
SETLOCAL EnableDelayedExpansion
SET num=0
FOR /F "tokens=*" %%A in (IPlist.txt) do (
SET /A num+=1
ECHO Flag > RoboRunNum.!num!
START robocopy "\\networkfolder" \\%%A ^& del RoboRunNum.!num!
)
:Check
if exist RoboRunNum.* GOTO CHECK
echo Robocopy Processes fave Finished
I am very new to this. Please help me
I was trying to write a batch file program to count number of files in a folder and assign that to a variable and display it to verify that it has been stored
please help me with the syntax,
thank you in advance
-VK
I'm going to assume you do not want to count hidden or system files.
There are many ways to do this. All of the methods that I will show involve some form of the FOR command. There are many variations of the FOR command that look almost the same, but they behave very differently. It can be confusing for a beginner.
You can get help by typing HELP FOR or FOR /? from the command line. But that help is a bit cryptic if you are not used to reading it.
1) The DIR command lists the number of files in the directory. You can pipe the results of DIR to FIND to get the relevant line and then use FOR /F to parse the desired value from the line. The problem with this technique is the string you search for has to change depending on the language used by the operating system.
#echo off
for /f %%A in ('dir ^| find "File(s)"') do set cnt=%%A
echo File count = %cnt%
2) You can use DIR /B /A-D-H-S to list the non-hidden/non-system files without other info, pipe the result to FIND to count the number of files, and use FOR /F to read the result.
#echo off
for /f %%A in ('dir /a-d-s-h /b ^| find /v /c ""') do set cnt=%%A
echo File count = %cnt%
3) You can use a simple FOR to enumerate all the files and SET /A to increment a counter for each file found.
#echo off
set cnt=0
for %%A in (*) do set /a cnt+=1
echo File count = %cnt%
#echo off
setlocal enableextensions
set count=0
for %%x in (*.txt) do set /a count+=1
echo %count%
endlocal
pause
This is the best.... your variable is: %count%
NOTE: you can change (*.txt) to any other file extension to count other files.....
The mugume david answer fails on an empty folder; Count is 1 instead of a 0 when looking for a pattern rather than all files. For example *.xml
This works for me:
attrib.exe /s ./*.xml | find /v "File not found - " | find /c /v ""
This might be a bit faster:
dir /A:-D /B *.* 2>nul | find /c /v ""
`/A:-D` - filters out only non directory items (files)
`/B` - prints only file names (no need a full path request)
`*.*` - can filters out specific file names (currently - all)
`2>nul` - suppresses all error lines output to does not count them
To build for statement you should know some details at first.
for /F %%i in ('dir /A:-D /B *.* 2^>nul ^| find /c /v ""') do set "COUNT=%%i"
The example above would work, but if you want to copy paste it into another for-expression - might not.
The for /F ... expression by default has ; character as EOL character and space+tabulation characters as line separators.
If you use a file path as input in for-expression, then you can override these characters:
for /F "eol= delims=" %%i in (";My file path") do echo.Value: %%i
Where the end of eol= might not visible here. It is just a file path invalid not printable character, in this case - code 04. In most consoles and editors (except stackoverflow itself) you can type it as:
press ALT
type 04 from numeric keypad
release ALT
Another issue avoid here is always reset variable you want to use before the for-expression in case if for-expression is not executed:
set FILE=undefined
for /F %%i in (";My file path") do set "FILE=%%i"
echo.FILE=%FILE%
The fastest code for counting files with ANY attributes in folder %FOLDER% and its subfolders is the following. The code is for script in a command script (batch) file.
#for /f %%a in ('2^>nul dir "%FOLDER%" /a-d/b/-o/-p/s^|find /v /c ""') do set n=%%a
#echo Total files: %n%.
Change into the directory and;
attrib.exe /s ./*.* |find /c /v ""
EDIT
I presumed that would be simple to discover. use
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "batchfile.bat";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
I run this and the variable output was holding this
D:\VSS\USSD V3.0\WTU.USSD\USSDConsole\bin\Debug>attrib.exe /s ./*.* | find /c /v "" 13
where 13 is the file count. It should solve the issue
for /F "tokens=1" %a in ('dir ^| findstr "File(s)"') do echo %a
Result:
C:\MyDir> for /F "tokens=1" %a in ('dir ^| findstr "File(s)"') do #set FILE_COUNT=%a
C:\MyDir> echo %FILE_COUNT%
4 // <== There's your answer
FOR /f "delims=" %%i IN ('attrib.exe ./*.* ^| find /v "File not found - " ^| find /c /v ""') DO SET myVar=%%i
ECHO %myVar%
This is based on the (much) earlier post that points out that the count would be wrong for an empty directory if you use DIR rather than attrib.exe.
For anyone else who got stuck on the syntax for putting the command in a FOR loop, enclose the command in single quotes (assuming it doesn't contain them) and escape pipes with ^.
I have used a temporary file to do this in the past, like this below.
DIR /B *.DAT | FIND.EXE /C /V "" > COUNT.TXT
FOR /F "tokens=1" %%f IN (COUNT.TXT) DO (
IF NOT %%f==6 SET _MSG=File count is %%f, and 6 were expected. & DEL COUNT.TXT & ECHO #### ERROR - FILE COUNT WAS %%f AND 6 WERE EXPECTED. #### >> %_LOGFILE% & GOTO SENDMAIL
)
With a for loop:
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
echo %count%
Without/avoiding for loop:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
set count=%errorlevel%
echo %count%
Tested in Win 10 cmd
Solution
Requires enabling Windows Subsystems For Linux
Ensure directoryToCount is set to the respective directory
SET directoryToCount=C:\Users\
dir %directoryToCount% > contentsOfDir.txt
echo cat contentsOfDir.txt ^| grep File > countFiles.sh
sh countFiles.sh
del countFiles.sh
del contentsOfDir.txt
Explanation
In both bash and batch environments, the output of a command can be redirected to a file using the > operator.
For example, echo hello world > myFile.txt will produce a file named myFile.txt with hello world as its text.
In a bash environment, one can cat the contents of a File and grep a particular line from the file containing a specified pattern.
For example, cat myFile.txt | grep hello will return lines containing hello
If Windows Subsystems for Linux is enabled, then one can execute sh from a Command Prompt to access a linux-like environment.
Therefore, we can solve this by doing the following
Use dir to acquire a list of files in the directory, as well as the number of files
Redirect the output of dir to a file (perhaps named contentsOfDir.txt).
Create a .sh file to grep for File from contentsOfDir.txt
Call the .sh file from command prompt to invoke the grep
Delete the .sh file
Delete contentsOfDir.txt