Batch: check for the PID each second - loops

I need to check which is the PID of, for example, "notebook.exe" if this process is running in the tasklist, so I need to check this each second:
If I running this while the program is running, works:
echo off
cls
SETLOCAL EnableExtensions
SETLOCAL EnableDelayedExpansion
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='notebook.exe'" get ProcessID ^| findstr [0-9]') do set MyPID=%%a
#echo %USERNAME%-%COMPUTERNAME%-%MyPID%
But I need check this each second. The same but into a Loop, but doesn't work (MyPID variable is empty)
echo off
cls
SETLOCAL EnableExtensions
SETLOCAL EnableDelayedExpansion
for /L %%n in (1,0,10) do (
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='notebook.exe'" get ProcessID ^| findstr [0-9]') do set MyPID=%%a
#echo %USERNAME%-%COMPUTERNAME%-%MyPID%
)
Is it possible?

You are trying to use a variable that you have set inside a for loop. Since batch is executed line by line and code blocks (such as loops) are counted as one line, this will not work because batch will first expand %MyPID% to whatever it value was, and then execute the entire for loop.
You came close to the way to fix this. Using Enable DelayedExpansion is part of the trick. but you also need to use ! around variables inside the loop to mark them as delayed.
So in conclusion, this should work:
#echo off
cls
SETLOCAL EnableExtensions
SETLOCAL EnableDelayedExpansion
for /L %%n in (1,0,10) do (
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='notebook.exe'" get ProcessID ^| findstr [0-9]') do set MyPID=%%a
echo %USERNAME%-%COMPUTERNAME%-!MyPID!
)
However, note that loops in batch are made much easier using labels, so this would work too, removing the need for the delayed expansion:
#echo off
cls
SETLOCAL EnableExtensions
:loop
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='notebook.exe'" get ProcessID ^| findstr [0-9]') do set MyPID=%%a
echo %USERNAME%-%COMPUTERNAME%-%MyPID%
timeout /t 1 /nobreak >nul
goto :loop
the timeout /t 1 also makes sure it waits 1 second before going back to :loop

This is better done in PowerShell:
while ($true) {
Start-Sleep -Seconds 1
"{0}-{1}-{2}" -f $env:UserName,$env.ComputerName,(Get-Process -Name "Notebook.exe").id
}

Related

assigning a piped command to the variable batch

I'm having trouble assigning a command that counts the number of times a file in a directory appears to a variable.
I found that I should do this - (^ |) but when I do it and echo the variable, nothing is displayed, and there should be a number of occurrences.
My code:
#echo off
setlocal enableextensions
for /f "tokens=*" %%i in ('dir /b C:\Users\AD10FC\IdeaProjects\collateral\db-resources\release | findstr /B "!first%!-" | find /c /v ""') do set VAR=%%i
echo %VAR%
There is no need to use findstr.exe in your code to filter the leading strings, because you can filter those directly in Dir:
#Echo Off
SetLocal EnableExtensions
Set "first=LeadingString"
For /F "EOL=? Delims=" %%G In ('"Dir /B /A:-D "%UserProfile%\IdeaProjects\collateral\db-resources\release\%first%-*" | "%SystemRoot%\System32\find.exe" /V /C """') Do Set "VAR=%%G"
Echo(%VAR%
Pause
Also for the specific task you're performing, you may find the following works better for you:
#Echo Off
SetLocal EnableExtensions
Set "first=LeadingString"
For /F %%G In ('""%SystemRoot%\System32\xcopy.exe" "%UserProfile%\IdeaProjects\collateral\db-resources\release\%first%-*" . /LQH"') Do Set "VAR=%%G"
Echo(%VAR%
Pause

Find current console size in batch

I am working on a batch file and i need to print hyphens ( - ) across the screen as a separator. Is there a fast (under two seconds) command that can do this?
I have done multiple search queries and could not find the answer on various websites.
(code to find screen size)
for /l %%a in (1,1,%screen size var%) do (set "line=%line%-")
echo %line%
The output should show a line of hyphens across the console.
This is untested, but based upon the output from Mode CON as used in gjpio's answer:
#Echo Off
For /F "Skip=4Tokens=1*Delims=:" %%A In ('Mode CON')Do (For /L %%C In (1,1,%%B)Do #Set/P "=-"<Nul)&Echo( &GoTo :Draw
:Draw
Pause
If you intend to use the separator multiple times within your script you could save it to a variable:
#Echo Off
For /F "Skip=4Tokens=1*Delims=:" %%A In ('Mode CON')Do (For /L %%C In (1,1,%%B)Do (Call Set "separator=%%separator%%-"))&GoTo :Next
:Next
Echo Welcome to %~nx0
Echo %separator%
Pause
As a final afterthought, and just in case you feel that it would perform quicker, I thought I'd better provide a version using delayed expansion too:
#Echo Off&SetLocal EnableDelayedExpansion&Set "separator="
For /F "Skip=4Tokens=1*Delims=:" %%A In ('Mode CON')Do (For /L %%C In (1,1,%%B)Do Set "separator=!separator!-")&GoTo :Next
:Next
Rem Uncomment the next line if you don't want to use delayed expansion in the rest of the script
::EndLocal&Set "separator=%separator%"
Rem Your code goes here
Echo Welcome to %~nx0
Echo %separator%
Pause
As an addition to all of the above, you could also leverage powershell to do this too:
#Echo Off
For /F %%A In ('Powershell -NoP "Write-Host('-' * $(Get-Host).UI.RawUI.WindowSize.Width)"')Do Set "separator=%%A"
Echo Welcome to %~nx0
Echo %separator%
Pause
If you can work out the batch commands retrieve the columns value you could use the output from the MODE command;
MODE CON
C:\Users\gjp>mode con
Status for device CON:
----------------------
Lines: 9001
Columns: 120
Keyboard rate: 31
Keyboard delay: 1
Code page: 850
I would suggest you to use the following code:
#echo off
setlocal EnableDelayedExpansion
for /F "skip=4 tokens=2" %%A IN ('mode CON') do (
for /L %%B IN (1 1 %%A) do set "hyphen=!hyphen!-"
echo !hyphen!
goto :subroutine
)
:subroutine
echo You may continue here
pause
which is a bit complicated, but should do what you want.
The code searches for the columns in mode CON's command output and adds to hyphen variable these accordingly.

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 get the list of files from the directory one by one into a variable

I am new to Batch script,
by using the following code
setlocal enabledelayedexpansion enableextensions
set LIST=
for %%x in (D:\all_files\*.csv) do set LIST=!LIST! %%x
set LIST=%LIST:~1%
echo %LIST%
i am getting the filenames with directory and also with a Paragraph
but i need file names alone one by one like below into a Variable of %LIST%
file1.csv
file2.csv
file3.csv
can any one please help us
I hope, I got your intentions right.
Instead of a variable, just loop over output of dir /b
:loop
echo still waiting...
timeout /t 10
set "ok=yes"
for /f "delims=" %%a in ('dir /b "D:\all_files\*.csv"') do (
if not exist "C:\%%a" set "ok=no"
)
if "%ok%" == "no" goto :loop
echo all there...
call process1.bat

Batch File: Assign random line of text file as variable for later use

I'm trying to write a very simple batch file for personal use...It's complete except for one thing I'm stumped on. Hopefully this is an easy fix (I'm effectively illiterate when it comes to code).
Basically what I'm trying to do is have the script choose a random line from a text file, do this a couple times with a couple different text files, then I wish to assign the output from each text file to a variable so that I can easily use them in various combinations...then repeat the process.
Here is what I have right now...
#ECHO OFF
:START
SETLOCAL
SETLOCAL EnableDelayedExpansion EnableExtensions
SET "list1=list1.txt"
FOR /f %%a IN ('type "%list1%"^|find /c /v ""') DO SET /a numlines=%%a
SET /A list1random=(%RANDOM% %% %NumLines%)
IF "%list1random%"=="0" (SET "list1random=") ELSE (SET "list1random=skip=%list1random%")
FOR /F "usebackq tokens=* %list1random% delims=" %%A IN (`TYPE %list1%`) DO (
>> output.txt ECHO %%A
)
:Finish
ENDLOCAL
GOTO START`
This procures the random line, and spits it to a text file. All is well, next step, take that random result and assign it to a variable...
#ECHO OFF
:START
SETLOCAL
SETLOCAL EnableDelayedExpansion EnableExtensions
SET "list1=list1.txt"
FOR /f %%a IN ('type "%list1%"^|find /c /v ""') DO SET /a numlines=%%a
SET /A list1random=(%RANDOM% %% %NumLines%)
IF "%list1random%"=="0" (SET "list1random=") ELSE (SET "list1random=skip=%list1random%")
FOR /F "usebackq tokens=* %list1random% delims=" %%A IN (`TYPE %list1%`) DO (
SET output1=%%A
)
>> output.txt ECHO %output1%
:Finish
ENDLOCAL
GOTO START
Now the output ceases to be random...instead it is always the last line of the referenced text file.
EDIT: The site suggested another question that was similar to mine. However, that person was having trouble getting the script to choose a valid line. I get a valid line every time, and a random one too (when I check it via echo), but a non-random line when proceeding on, assigning the output to a variable. I don't understand because it seems like a post-facto derandomization. I.E. the difference between the two scripts has nothing to do with procuring the random result, only what to do with that result AFTER it has it, right?
I appreciate any help in advance, this is the last step before I know everything I need to finish this, I'm excited!
Sorry, you're right...anyways, I figured out a simple workaround, probably not the quickest in terms of processing time, but whatever. Basically allow the initial part of the script to spit out the random result to a text file (as seemed to work just fine) then reference the text file as a variable.
#ECHO OFF
:START
SET "list1=list1.txt"
FOR /f %%a IN ('type "%list1%"^|find /c /v ""') DO SET /a numlines=%%a
SET /A listchoice=(%RANDOM% %% %NumLines%)
IF "%listchoice%"=="0" (SET "listchoice=") ELSE (SET "listchoice=skip=%listchoice%")
FOR /F "usebackq tokens=* %listchoice% delims=" %%A IN (`TYPE %list1%`) DO (
>> listoutput.txt ECHO %%A
)
Set /p list=<listoutput.txt
>> result.txt ECHO %list%
:Finish
DEL listoutput.txt
GOTO START
This is easy to do in PowerShell using the built-in Get-Random cmdlet.
$line = (Get-Content file.txt | where { $_ } | Get-Random)
Which makes it also easy in batch.
set filename=file.txt
for /f "tokens=*" %%a in ('powershell -ex bypass -c "gc %filename% | ? { $_ } | Get-Random"') do (
set "var=%%a"
)
The where { $_ } clause is only necessary to filter out any blank lines. You can omit it if you know your file has none.

Resources