Suspend all processes from a specified folder - batch-file

What I'm trying to do is suspend multiple processes from a single folder in Windows 7. I can get a list of such proccessses using the following commands:
WMIC PROCESS WHERE 'ExecutablePath like "c:\\users%"' GET
or
WMIC PROCESS WHERE 'ExecutablePath like "c:\\users%"' LIST
Then I need to suspend the proccesses that are returned by those commands. I can do that by using PsSuspend software. So, the only thing I have troubles with is looping through the list and executing this command for each process. It's rather easy to do in bash scripts, but how do I do it easily in Windows? I would prefer to use a .bat file or something similar, so it won't get overly complicated.

Here's an example:
#Echo Off
SetLocal EnableExtensions
Rem Command
(Set WC=Process)
Rem Filter
(Set WF=ExecutablePath Like)
Rem Value
(Set FV=%UserProfile%)
Rem Output
(Set RO=ProcessID)
Rem Run
(Set RC=PsSuspend)
For /F "UseBackQ Skip=1" %%A In (
`WMIC %WC% Where "%WF% '%FV:\=\\%%%'" Get %RO%`) Do For %%B In (%%A
) Do %RC% %%B
I changed line 9 to %UserProfile% you can change it back to C:\Users if you think I've assumed wrongly.

Related

.bat file that will start a process, get its PID, monitor its running condition

I am basically trying to write a script on WIN10 that will allow me to start a python script, monitor for it to complete before moving on the next step. This looks like it should work but it just loops at the 2s timer, even after I close the notepad windows. This is kind of a combination of 2 scripts I found on here so I may be way out to lunch on my methods.
#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%
::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!")
)
:check
set stillalive=no
for /f "tokens=2" %%b in ('tasklist') do (
set pid=%%b
if !pid! == %RETPIDS% (
set stillalive=yes
)
)
if %stillalive% == yes (
cls
echo/Oh! He's still there, I'll wait.
timeout /t 2 /nobreak
goto check
) else (
echo/He's not there anymore, start the party!!
)
pause>nul
If there is a simpler way of doing this that's fine, if I can get this working with notepad, it should be easy to adapt to suit my needs.
Thanks in advance.
It's necro, I know, but I looked for something similar and just ended up here. This did a trick and fixed the script:
Replace
(set "RETPIDS=/PID %%a !RETPIDS!")
with
(set "RETPIDS=%%a!RETPIDS!")
The thing is that RETPIDS value looked like /PID 18465 and pid value was like 18465 and there also was a mess up with !!, %%, "%%" stuff and condition therefore strangely triggered every time although it obviously shouldn't.
Also seems that yours RETPIDS implies a possibility of several PIDs in one string like "5147 8463 6521" but it defenitely won't work with your single !pid! comparison in a loop.

getting pid of process in windows server

I was looking for a script to get PID of a java process based on CommandLine value of task manager. ALl these java processes have similar COmmandLine value but differ in a keyword within the CommandLine. The process can't be identified by the image name because they all have same java.exe. Is there a way? I've placed below code based on npocmaka's answer
#echo off
setlocal enableDelayedExpansion
set "command_line="%1""
set "command_line=!command_line:"=%%!"
echo ~~!command_line!~~
for /f "usebackq tokens=* delims=" %%# in (
`wmic process where 'CommandLine like "%command_line%"' get /format:value`
) do (
for /f %%$ in ("%%#") do (
set "%%$"
)
)
echo %ProcessId%
I'm using a keyword in CommandLine to identify the PID. Yet when I execute this script, I get the wrong PID. I'm assuming its returning the scripts PID as the script may also contain the keyword. The argument while executing the script is taken as keyword
WMIC PROCESS is what you need.Though you'll need some tricks to use it from batch.I've used more complex command line which contains quotes ,brackets,spaces, file separators.... You'll need to change it and set the value you want.
First you'll need to double every backslash in the command line(the script should do it I mean).Quotes also can be a problem and need to be replaced with % or escaped with \" (WMIC uses WQL a subset of SQL commands and % is used as wildcard).Another thing is you need to process the result twice with FOR loop to rid-off unwanted special characters./Format:Value can be used for direct declaring variable/value pairs.So here it is:
#echo off
setlocal enableDelayedExpansion
:: !!!!!!!!!
set "command_line="C:\Program Files (x86)\Dropbox\Client\Dropbox.exe" /systemstartup"
:: !!!!!!!!
set "command_line=!command_line:\=\\!"
set "command_line=!command_line:"=%%!"
::or
::set "command_line=!command_line:"=\"!"
rem echo ~~!command_line!~~
for /f "usebackq tokens=* delims=" %%# in (
`wmic process where 'CommandLine^="!command_line!"' get /format:value`
) do (
for /f %%$ in ("%%#") do (
set "%%$"
)
)
echo %ProcessId%
wmic process where name='explorer.exe' get commandline, pid /format:list
is one way. Also see tasklist /v.

Windows batch file: get last folder name from path

I'm trying to rename .jpg files which is in one of many subdirectories of e:\study\pubpmc\test\extracted.
I want to rename files to LastFolderName_ImageName.jpg.
(For example if Figure1.jpg is in e:\study\pubpmc\test\extracted\folder1
I want it to be renamed like this: folder1_Figure1.jpg)
So I need to take out the last folder name from the file's path.
Since it's my first time with batch scripting, I'm having a hard time.
I googled and made code similar to it
but it doesn't seem to work out.
Can you help me with it and tell me where I've done wrong?
Thank you! :)
#echo off
cd /D "e:\study\pubpmc\test\extracted"
for /r %%f in (*.jpg) do (
set mydir=%%~dpf
set mydir=%mydir:\=;%
for /f "tokens=* delims=;" %%i in (%mydir%) do call :LAST_FOLDER %%i
goto :EOF
:LAST_FOLDER
if "%1"=="" (
#echo %LAST%
goto :EOF
)
set LAST=%1
SHIFT
goto :LAST_FOLDER
)
JosefZ explains the obvious problems with your code, but he failed to point out a subtle problem, though his code fixed it:
FOR /R (as well as the simple FOR) begin iterating immediately, before it has finished scanning the disk drive. It is possible for the loop to reiterate the already named file! This would cause it to be renamed twice, giving the wrong result. The solution is to use FOR /F with command 'DIR /B', because FOR /F always processes the command to completion before iterating.
JosefZ also provides code that works for most situations. But there is a much simpler solution that works always:
#echo off
for /f "delims=" %%A in (
'dir /b /s /a-d "e:\study\pubpmc\test\extracted\*.jpg"'
) do for %%B in ("%%A\..") do ren "%%A" "%%~nxB_%%~nxA"
The "%%A\.." treats the file name as a folder and walks up to the parent folder. So %%~nxB gives the name of the parent folder.
The command could be run as a long one liner, directly from the command line (no batch):
for /f "delims=" %A in ('dir /b /s /a-d "e:\study\pubpmc\test\extracted\*.jpg"') do #for %B in ("%A\..") do #ren "%A" "%~nxB_%~nxA"
Avoid using :label and :: label-like comment inside (command block in parentheses). Using any of them within parentheses - including FOR and IF commands - will break their context.
Using variables inside (command block in parentheses). Read EnableDelayedExpansion: Delayed Expansion will cause variables to be expanded at execution time rather than at parse time [and CLI parses all the (command block in parentheses) at once]
Next script should work for you. Note rename statement is merely echoed for debugging purposes.
#ECHO OFF >NUL
SETLOCAL enableextensions disabledelayedexpansion
set "fromFolder=e:\study\pubpmc\test\extracted"
rem my debug setting set "fromFolder=D:\path"
for /F "tokens=*" %%f in ('dir /B /S /A:D "%fromFolder%\*.*"') do (
set "mydir=%%~ff"
set "last=%%~nxf"
call :renameJPG
)
#ENDLOCAL
goto :eof
:renameJPG
rem echo "%mydir%" "%last%"
for /f "tokens=*" %%i in ('dir /B /A:-D "%mydir%\*.jpg" 2^>nul') do (
echo ren "%mydir%\%%~nxi" "%last%_%%~nxi"
)
goto :eof
Resources:
SETLOCAL, disableDelayedExpansion, ENDLOCAL etc.
An A-Z Index of the Windows CMD command line
Windows CMD Shell Command Line Syntax
I already wrote a function for that. You give it any path and it returns you only it's filename or pathname. Works for any path: Url, Windows path, Linux path, etc...
Copy this function at the end of your batch script: (Instructions below)
rem ===========================================================================
:Name_From_Path
SetLocal
set _TMP_FOLDERNAME=%1
for %%g in ("%_TMP_FOLDERNAME%") do set _TMP_FOLDERNAME=%%~nxg
EndLocal & set _Name_From_Path=%_TMP_FOLDERNAME%
goto :EOF
rem ===========================================================================
Usage:
CALL :Name_Of_Path e:\study\pubpmc\test\extracted\folder1
ECHO %_Name_From_Path%
Result: folder1
If your program or com file traverses these folders when renaming, then it should be able to get the present working directory ( path ), pwd. You may be able to chop everything but the LAST_FOLDER out of this by also creating a PREVIOUS_FOLDER and doing a string replacement.
Or you may be able to break the folder names at the '\' token from the pwd into an array and use a -1 array reference to get the last folder name.
In any circumstance you'll want to check for a present working directory command.
If your creating a large text list of all these and issuing a single call to the batch file.
Then you may be better off with something like:
(Symmantic code warning )
(copy) /folderbase/some_folder/oneormore1/image_from_oneormore1.jpg (to) /folderbase/some_folder/oneormore1/oneormore1_image_from_oneormore1.jpg
Instead of copy, window uses rename, linux uses mv.
The latter example would require simply creating a duplicate list and replacing the \ with a _ while parsing through the tokens.
The code you've given is difficult to make sense of, so its hard to discern if you can simple concatenate the current folder and image name (stringify) and then write or rename them where they are.

Carrying variables into new command prompt windows

I want a batch file that opens and:
Sets all items in list.txt to variable v one at a time.
For each of the items in list.txt to open a command prompt and run starter.bat
Carry variable v into starter.bat
My code
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=*" %%v in (C:\users\anhall\desktop\test\list.txt) DO START c:\users\anhall\desktop\test\starter.bat
ENDLOCAL & SET computer=%v%
this is just an example of what will be in there, when I get it all figured out there should be a couple hundred items in the list. But I will probably break it down into smaller lists for ease of running.
list.txt
nhn-0073
nhn-0115
nhn-0846
This is what I end up with on the primary window:
I can see that its not working because it doesn't even carry to ENDLOCAL & SET computer=
My main concern is carrying the variable into each of the new windows. I know this is possible but I can't get it to work.
Completed Code
My code
SETLOCAL
FOR /F "tokens=*" %%v in (C:\users\anhall\desktop\test\list.txt) DO START c:\users\anhall\desktop\test\starter.bat %%v
changes to starter.bat
changed variable to %1
Just pass it in on the command line:
for /F %%v in (YourFile.txt) do start c:\users\anhall\desktop\test\starter.bat %%v
Modify your starter.bat file to use %1 to receive the variable from the command line.
:: Starter.bat - replace echo with your actual command
#echo %1
(Doing it from the command line means you never change the computer environmental variable, so you can remove the & SET at the end of your first batch file.)

How do I exclude specific file names from an MS DOS dir list?

I am creating an MS DOS batch script that needs to list every .bat file in the current directory, but not show autoexec.bat or other utilities or systems .bat files that shouldn't be run by the user.
I currently have DIR "*.bat" /B /P
This lists all .bat files appropriately, but it shows autoexec.bat. How would I exclude that from the list? Also slightly important, how could I chop off the file extensions and show more than the 7-characters DOS limits files to?
Constraints: I am not able to use a DOS version above WinME. That is the version I am using.
Thanks for any help.
EDIT:
There is plenty of information on the internet about doing this, but it is all in the windows command processor, not MS DOS. Please understand that DOS and the Command Prompt are not the same thing.
#echo off
setlocal EnableDelayedExpansion
rem Add more names separated with slashes here:
set exclude=/autoexec/
for %%a in (*.bat) do (
if "!exclude:/%%~Na/=!" equ "%exclude%" (
echo %%~Na
)
)
EDIT: Some explanations added
Batch file processing is slow, so you should use techniques that allows a Batch file to run faster. For example:
Try to use the minimum lines/commands to achieve a certain result. Try to avoid external commands (*.exe files) like find, findstr, fc, etc. specially if they work on small amounts of data; use if command instead.
Use for %%a in (*.bat)... instead of for /F %%a in ('dir /B *.bat').... The second method requires to execute cmd.exe and store its output in a file before for command can process its lines.
Avoid pipes and use redirections instead. A pipe require the execution of two copies of cmd.exe to process the command at each side of the pipe.
A simple way to check if a variable contain a given string is trying to delete the string from the variable: if the result is different then the string exists in the variable: if "!variable:%string%=!" neq "%variable%" echo The string is in the variable.
Previous method may also be used to check if a variable have anyone of a list of values: set list=one two three, if "!list:%variable%=!" neq "%list%" echo The variable have one value from the list. If the values of the list may have spaces, they must be separated by another delimiter.
EDIT: New version added as answer to new comments
The easiest way to pause one page at a time is to use more filter this way:
theBatchFile | more
However, the program must reorder the output in order to show it in columns. The new version below achieve both things, so it does not require more filter; you just need to set the desired number of columns and rows per page.
#echo off
setlocal EnableDelayedExpansion
rem Add more names separated with slashes here:
set exclude=/autoexec/
rem Set the first two next variables as desired:
set /A columns=5, rows=41, wide=(80-columns)/columns, col=0, row=0
rem Create filling spaces to align columns
set spaces=
for /L %%a in (1,1,%wide%) do set spaces= !spaces!
set line=
for %%a in (*.bat) do (
if "!exclude:/%%~Na/=!" equ "%exclude%" (
rem If this column is less than the limit...
set /A col+=1
if !col! lss %columns% (
rem ... add it to current line
set name=%%~Na%spaces%
set "line=!line!!name:~0,%wide%! "
) else (
rem ... show current line and reset it
set name=%%~Na
echo !line!!name:~0,%wide%!
set line=
set /a col=0, row+=1
rem If this row is equal to the limit...
if !row! equ %rows% (
rem ...do a pause and reset row
pause
set row=0
)
)
)
)
rem Show last line, if any
if defined line echo %line%
Antonio
attrib +h autoexec.bat
should hide autoexec.bat and it should thus not appear in the list
DIR "*.bat" /B /P | find /v "autoexec" | for %i in (*.bat) do #echo %~ni
Using for to process each file name individually:
setlocal enabledelayedexpansion
for /f %%i in ('dir "*.bat" /b') do (
set system=0
if "%%i"=="autoexec.bat" set system=1
if "%%i"=="somesystem.bat" set system=1
if !system!==0 echo %%i
)
Another method without variables:
for /f %%i in ('dir "*.bat" /b') do call :test %%i
goto continue
:test
if "%1"=="autoexec.bat" goto :eof
if "%1"=="somesystem.bat" goto :eof
echo %1
goto :eof
:continue
For both, you can add new filenames to exclude from the list.

Resources