Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

fast way to count the number of running processes for a specific program

Sep
70
1
I've created a btm to process flac files in various ways; test them, convert wav to flac, reconvert a flac file to my compression settings, etc. I run the number of instances of flac.exe as I have threads. I've discovered that getting the number of currently running flac instances is slow. I use

rem numproc is the number of files I've processed. I skip the number of flac instances stuff until I get above the number of threads I have to save time.

:processfile [filename]
iff %numproc% ge %number_of_processors then
set ninstancetext=%@pid[%program.exe, +]
iff %ninstancetext ne 0 then
set ninstances=%@words[%ninstancetext]
else
set ninstances=0
endiff
else
set ninstances=%numproc%
endiff
iff %ninstances lt %number_of_processors then
set numproc=%@inc[%numproc%]
iff %testmode eq 0 then
echos Processing ``
else
echos Testing ``
endiff
echo %filename
start /inv /belownormal %program %flacswitches %filename
else
delay /m 100
goto processfile
endiff
return

On my Ryzen 7950X Each of the %@pid calls takes about .1 seconds. I tried processmonitor, but it doesn't seem to allow me to keep track of how many processes are running

processmonitor notepad.exe started forever beep 300
processmonitor notepad.exe ended forever beep 600

The following happens:

1. Run notepad and hear the 300 HZ beep.
2. Run another notepad and hear nothing.
3. Close the second notepad and hear nothing.
4. Close the first notepad and hear the 600 HZ beep.

Any ideas would be helpful.
 
You're right, @PID is slow. Here (at 3.5 GHz) I get about 0.04 sceonds. But I can't think of anything built-in (to TCC or Windows) that will be faster. I have a plugin that exports @EXEPIDS[exename] (like @PID[exename,+] but 10~25 times the speed depending on how you test. I'll say more if you're interested.
 
I've created a btm to process flac files in various ways; test them, convert wav to flac, reconvert a flac file to my compression settings, etc. I run the number of instances of flac.exe as I have threads. I've discovered that getting the number of currently running flac instances is slow. I use

rem numproc is the number of files I've processed. I skip the number of flac instances stuff until I get above the number of threads I have to save time.

:processfile [filename]
iff %numproc% ge %number_of_processors then
set ninstancetext=%@pid[%program.exe, +]
iff %ninstancetext ne 0 then
set ninstances=%@words[%ninstancetext]
else
set ninstances=0
endiff
else
set ninstances=%numproc%
endiff
iff %ninstances lt %number_of_processors then
set numproc=%@inc[%numproc%]
iff %testmode eq 0 then
echos Processing ``
else
echos Testing ``
endiff
echo %filename
start /inv /belownormal %program %flacswitches %filename
else
delay /m 100
goto processfile
endiff
return

On my Ryzen 7950X Each of the %@pid calls takes about .1 seconds. I tried processmonitor, but it doesn't seem to allow me to keep track of how many processes are running

processmonitor notepad.exe started forever beep 300
processmonitor notepad.exe ended forever beep 600

The following happens:

1. Run notepad and hear the 300 HZ beep.
2. Run another notepad and hear nothing.
3. Close the second notepad and hear nothing.
4. Close the first notepad and hear the 600 HZ beep.

Any ideas would be helpful.
Code:
:processfile [filename]
    iff %numproc% ge %number_of_processors then
      set ninstancetext=%@pid[%program.exe, +]
      iff %ninstancetext ne 0 then
        set ninstances=%@words[%ninstancetext]
      else
        set ninstances=0
      endiff
    else
      set ninstances=%numproc%
    endiff
    iff %ninstances lt %number_of_processors then
      set numproc=%@inc[%numproc%]
      iff %testmode eq 0 then
        echos Processing ``
      else
        echos Testing ``
      endiff
      echo %filename
      start /inv /belownormal %program %flacswitches %filename
    else
        delay /m 100
        goto processfile
    endiff
    return
 
Last edited:
ISAPP is also very slow too, probably for the same reason.

Code:
v:\> timer /q & do i=1 to 1000 ( if isapp tcc.exe noop ) & timer
Timer 1 off: 13:41:14  Elapsed: 0:00:29.290

v:\> timer /q & do i=1 to 1000 ( if "%@exepids[tcc.exe]" != "" noop ) & timer
Timer 1 off: 13:41:28  Elapsed: 0:00:01.544
 
You're right, @PID is slow. Here (at 3.5 GHz) I get about 0.04 sceonds. But I can't think of anything built-in (to TCC or Windows) that will be faster. I have a plugin that exports @EXEPIDS[exename] (like @PID[exename,+] but 10~25 times the speed depending on how you test. I'll say more if you're interested.
Yes, I'm definitely interested.
 
You can get it like this.

Code:
copy "ftp://vefatica.net/4plugins/x64/4utils64.zip"

It has a lot of stuff in it, notably @EXEPIDS[].

Code:
v:\> help @exepids

@EXEPIDS[appname[.exe]] = space separated list (possibly empty) of PIDs for appname

Put the DLL in a "plugins" subdirectory in TCC's home directory. I'll be back later.
 
Code:
E:\Utils>echo %@pid[msedge.exe,+]
8668 19044 18444 19460 19588 20280 13356 13120 13204 12348 20348 21128 22368 9312 26480 25216 11480

Is there a way to count all of the pids for msedge.exe?

Joe

Ref: @PID TCC internal variable function
 
Yes, there is;
Code:
E:\Utils>timer echo %@pid[msedge.exe,+] ^n %@fields[%@pid[msedge.exe,+]]
8668 19044 18444 19460 19588 20280 13356 13120 13204 12348 20348 21128 22368 9312 26480 25216 23504 10040 10644 15836 25184
 21

ADDED: Timer 1 off: 18:31:49 Elapsed: 0:00:00.007

Joe
 
You can get it like this.

Code:
copy "ftp://vefatica.net/4plugins/x64/4utils64.zip"

It has a lot of stuff in it, notably @EXEPIDS[].

Code:
v:\> help @exepids

@EXEPIDS[appname[.exe]] = space separated list (possibly empty) of PIDs for appname

Put the DLL in a "plugins" subdirectory in TCC's home directory. I'll be back later.

I wonder why mine is so much slower
[E:\a]timer /q & do i=1 to 1000 ( if isapp tcc.exe noop ) & timer
Timer 1 off: 19:13:53 Elapsed: 0:01:16.284

[E:\a]timer /q & do i=1 to 1000 ( if "%@exepids[tcc.exe]" != "" noop ) & timer
Timer 1 off: 19:14:17 Elapsed: 0:00:03.716

[E:\a]ver

TCC 32.10.21 x64 Windows 11 [Version 10.0.22631.3593]

[E:\a]
Is there a way to only enable the parts of this plugin that I want?
 
I don't know about the speed. Your computer is faster than my 3.5 GHz, right? Could it be Windows or your CPU saving energy? I don't know about such things. Do you have a heck of a lot of stuff going on in the background? I'm on Windows 10 which idles at about 90 processes. Here's a simpler test (note, it's 10000).

Code:
v:\> timer /q & do i=1 to 10000 ( noop ) & timer
Timer 1 off: 20:20:28  Elapsed: 0:00:01.991

There's no way to disable anything. What would be the point?
 
I don't know about the speed. Your computer is faster than my 3.5 GHz, right? Could it be Windows or your CPU saving energy? I don't know about such things. Do you have a heck of a lot of stuff going on in the background? I'm on Windows 10 which idles at about 90 processes. Here's a simpler test (note, it's 10000).

Code:
v:\> timer /q & do i=1 to 10000 ( noop ) & timer
Timer 1 off: 20:20:28  Elapsed: 0:00:01.991

There's no way to disable anything. What would be the point?

I get
[E:\a]timer /q & do i=1 to 10000 ( noop ) & timer
Timer 1 off: 20:46:23 Elapsed: 0:00:03.306

[E:\a]
I have 225 processes running currently. My computer is on the performance power plan so nothing sleeping.
I guess I'm a simple person so only want noop and %@exepid. Does your plugin modify the internal cd command? Perhaps Rex can use the method you are using since it is so much faster.
 
I don't know about the speed. Your computer is faster than my 3.5 GHz, right? Could it be Windows or your CPU saving energy? I don't know about such things. Do you have a heck of a lot of stuff going on in the background? I'm on Windows 10 which idles at about 90 processes. Here's a simpler test (note, it's 10000).

Code:
v:\> timer /q & do i=1 to 10000 ( noop ) & timer
Timer 1 off: 20:20:28  Elapsed: 0:00:01.991

There's no way to disable anything. What would be the point?

It looks like the plugin is creating a file tslog.log in the tcmd program folder. Can I have a version that doesn't do this? If it isn't too dificult I'd really just like a version that includes %@exepids, %@isapp, and noop.
 
Does your plugin modify the internal cd command?

In a way ... it's the CD that TCC calls first. But if you don't specify /H, /P, /K, or /F, it tells TCC "I'm not the guy you want" and TCC uses its internal CD. For that reason I'd expect mine to be (a few microseconds) slower.

It looks like the plugin is creating a file tslog.log in the tcmd program folder. Can I have a version that doesn't do this? If it isn't too dificult I'd really just like a version that includes %@exepids, %@isapp, and noop.

I'll think about the timestamp log. I prefer it to TCC's XHistory32 log. Custom/one-off plugins would be very difficult and I won't be doing that.
 
In a way ... it's the CD that TCC calls first. But if you don't specify /H, /P, /K, or /F, it tells TCC "I'm not the guy you want" and TCC uses its internal CD. For that reason I'd expect mine to be (a few microseconds) slower.



I'll think about the timestamp log. I prefer it to TCC's XHistory32 log. Custom/one-off plugins would be very difficult and I won't be doing that.

Do you mind telling me how you get the isapp and exepid information? Do you think it would be something Rex was interested in using?
 
Do you mind telling me how you get the isapp and exepid information? Do you think it would be something Rex was interested in using?
The info comes from the Win32 API function CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) (and a couple other functions for stepping through the data). I'm sure Rex is aware of it; TakeCmd.DLL imports it so I reckon it's used somewhere. I suspect @PID and ISAPP are using a much more robust strategy (based on EnumProcesses(), a guess) that exists for many purposes besides @PID and ISAPP.

The only (useful) things you get from a Toolhelp32Snapshot are ProcessID, thread_count, ParentProcessID, and (not_fully_qualified) module name. Those are sufficient for @EXEPIDS and @ISAPP but not for many of TCC's other purposes. The only things you get fron EnumProcesses are PIDs; getting further information requires a lot of bare-hands stuff.
 
Do you mind telling me how you get the isapp and exepid information? Do you think it would be something Rex was interested in using?

For now I can just load the plugin when this batch file is running. At the beginning I just do

plugin /l c:\folder\4utils64.dll

and at the end I tried

plugin /u c:\folder\4utils64.dll, but it says

TCC: (Sys) The system cannot find the file specified.
"c:\folder\4utils64.dll"

So I had to do plugin /u * this seems like a bug unless I don't understand the /u switch correctly.
 
The info comes from the Win32 API function CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) (and a couple other functions for stepping through the data). I'm sure Rex is aware of it; TakeCmd.DLL imports it so I reckon it's used somewhere. I suspect @PID and ISAPP are using a much more robust strategy (based on EnumProcesses(), a guess) that exists for many purposes besides @PID and ISAPP.

The only (useful) things you get from a Toolhelp32Snapshot are ProcessID, thread_count, ParentProcessID, and (not_fully_qualified) module name. Those are sufficient for @EXEPIDS and @ISAPP but not for many of TCC's other purposes. The only things you get fron EnumProcesses are PIDs; getting further information requires a lot of bare-hands stuff.
So what do you think Rex? Could you use this to speed up isapp and %@pid only? Is there a drawback for doing it this way?
 
For now I can just load the plugin when this batch file is running. At the beginning I just do

plugin /l c:\folder\4utils64.dll

and at the end I tried

plugin /u c:\folder\4utils64.dll, but it says

TCC: (Sys) The system cannot find the file specified.
"c:\folder\4utils64.dll"

So I had to do plugin /u * this seems like a bug unless I don't understand the /u switch correctly.

To unload a plugin, use PLUGIN /U with the plugin's internal name, not its filename. So:
Code:
plugin /u 4utils
 
I built a new 4UTILS in which the timestamp log is off by default. I can turn it on for non-transient, non-pipe shells in TCSTART.BTM. A new ZIP file is in place.

Code:
copy "ftp://vefatica.net/4plugins/x64/4utils64.zip"
 
I built a new 4UTILS in which the timestamp log is off by default. I can turn it on for non-transient, non-pipe shells in TCSTART.BTM. A new ZIP file is in place.

Code:
copy "ftp://vefatica.net/4plugins/x64/4utils64.zip"
Thanks this works great!
 
I get
[E:\a]timer /q & do i=1 to 10000 ( noop ) & timer
Timer 1 off: 20:46:23 Elapsed: 0:00:03.306

[E:\a]
I have 225 processes running currently. My computer is on the performance power plan so nothing sleeping.
I guess I'm a simple person so only want noop and %@exepid. Does your plugin modify the internal cd command? Perhaps Rex can use the method you are using since it is so much faster.
I added a beep so I could tell what was going on with no screen reader running and without one I get this
timer /q & do i=1 to 10000 ( noop ) & timer & beep
Timer 1 off: 0:38:10 Elapsed: 0:00:02.095
It is interesting that one of my screen readers has this impact. Still not as fast as yours, but I have other stuff that probably accounts for that.
 
I have a powershell script which does something fairly similar, only converting .flac files to .m4a (aac). I use this (below) to see how many instances are already running. I have no idea how long it takes, but the script has been working quite well for sometime now. If anyone is interested, I will post the script here. It is not perfect by any means, but it does do the job.

function count_instances{
get-ciminstance win32_process|where-object {$.Name -eq 'cmd.exe' -and $.CommandLine -match 'ffmpeg'}
}
 

Similar threads

Back
Top