CPU History on title

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

CPU History on title

#1 Post by einstein1969 » 30 Nov 2013 17:17

Hi,

I have made this code for display the CPU usage on title bar.

This show a history like a graphics on the title bar

I have two problem:

- There are output of set /a that i don't want visible.
- There are strange error on initial startup.

I have investigated but without being able to find why :( Experts Needed!

EDIT: thanks to penpen i have resolved. this is worked version on seven 32bit
An more readable and reliability (work better) version by penpen is here

Code: Select all

@echo off & setlocal EnableDelayedExpansion & if not "%1"=="" goto %1

chcp 850

rem sample of 5 seconds
start "" /B %0 title_cpu 5

pause

goto :eof


:title_cpu %1=sample_interval_sec
 shift

 set "counter=\Processore(_Total)\%% Tempo Processore" & rem italian version
 rem set "counter=\processor(_total)\%%%% processor time" & rem english version

           typeperf "!counter!" -si %1 | cmd /v:on /c"set S=_,..~-=ùùïî&set Bcpu= &for /L %%n in () do @(set v=&set /p v=&if defined v (set cpu=^!v:*,=^!&set cpu=  ^!cpu:~1,-6^!&set /a i=^!cpu:~0^,-2^!*10/100>nul 2>nul&if defined i for %%b in (^!i^!^) do @(set Bcpu=^!Bcpu^!^!S:~%%b,1^!^)&set Bcpu=^!Bcpu:~-50^!&title CPU:^!cpu:~-5^!%%  ^!Bcpu^!^)^) "

goto :eof


Image

Einstein1969
Last edited by einstein1969 on 03 Dec 2013 05:06, edited 3 times in total.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#2 Post by penpen » 30 Nov 2013 19:44

I'm currently using WinXP home, that has no typeperf.exe, so i only can try to solve this:
einstein1969 wrote:- There are output of set /a that i not want visible.
As you are using set /A wthin the cmd shell (and not a bat/cmd script),
you may want to redirect the unwanted output to nul (>nul), or
you may want to execute the part after the '|' from a bat/cmd script where this output isn't produced.

May i use this to simulate a valid output of typeref (format guessed),
or is the format wrong, or are there missing info/empty lines
(maybe such lines are causing the problem, if yes just filter using findstr/find)?

Code: Select all

setlocal enableDelayedExpansion
(
for /L %%a in (11,1,30) do for /L %%b in (0,1,9) do echo "!date!!time!","%%a.%%b01234"
)>"typeref.txt"
endlocal
Tomorrow i'll have a closer look at your script (too late now, sry).

penpen

Edit: Changed the typeref simulated output.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: CPU History on title

#3 Post by einstein1969 » 01 Dec 2013 11:48

Hi penpen,

thanks for replay.

I have added the >nul and 2>nul for the problem and now working.

The output of typeperf is this:

Code: Select all

"(PDH-CSV 4.0)","\\ACER-ASP-5100\Processore(_Total)\% Tempo Processore"
"12/01/2013 18:44:54.935","3.125000"
"12/01/2013 18:44:55.935","1.562500"
"12/01/2013 18:44:56.935","3.125000"


the first line may create problem but i don't wanted add other process. This use very low cpu for display this info. <0,3%

thanks again penpen!

einstein1969

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#4 Post by penpen » 01 Dec 2013 11:56

I think, i have found a possible problem:
You are using "for /L" and "set /P" to read the piped data.
There is no guarantee that the line is fully written to the pipe, before "set/p" has read the data fully.
Additionally there is no guarentee, that the typeperf output waits, until "set/p" has read the line, before additional data is written to the pipe.
As a result the lines could be messed up, especially, when loading first.

So you have to parse the data to lines, or better let another program (for example findstr) let do this.
So with the "set/A" redirected to nul this may help you (only the piped line):

Code: Select all

type typeperf.txt | cmd /V:ON /C "@echo off&set S=_,.-ùïî&set Bcpu=K&for /F %%a in ('findstr ","') do (set v=%%a&if defined v (set cpu=!v:*,=!&set cpu=  !cpu:~1,-6!&(set /a i=!cpu:~0,-2!*6/100)>nul&for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)&set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!))"

penpen

Edit: You may avoid using cmd /V:ON ... by using "typeperf ...|" within the for loop prior to findstr.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: CPU History on title

#5 Post by einstein1969 » 01 Dec 2013 15:54

penpen wrote:I think, i have found a possible problem:
You are using "for /L" and "set /P" to read the piped data.
There is no guarantee that the line is fully written to the pipe, before "set/p" has read the data fully.
Additionally there is no guarentee, that the typeperf output waits, until "set/p" has read the line, before additional data is written to the pipe.
As a result the lines could be messed up, especially, when loading first.

So you have to parse the data to lines, or better let another program (for example findstr) let do this.
So with the "set/A" redirected to nul this may help you (only the piped line):

Code: Select all

type typeperf.txt | cmd /V:ON /C "@echo off&set S=_,.-ùïî&set Bcpu=K&for /F %%a in ('findstr ","') do (set v=%%a&if defined v (set cpu=!v:*,=!&set cpu=  !cpu:~1,-6!&(set /a i=!cpu:~0,-2!*6/100)>nul&for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)&set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!))"

penpen

Edit: You may avoid using cmd /V:ON ... by using "typeperf ...|" within the for loop prior to findstr.


first i have tried

Code: Select all

@echo off & setlocal EnableDelayedExpansion & if not "%1"=="" goto %1

chcp 850

rem goto :test
rem goto :scopre

start "" /B %0 title_cpu 5

pause

goto :eof


:title_cpu %1=sample_interval_sec
 shift

 set "counter=\Processore(_Total)\%% Tempo Processore" & rem italian version
 rem set "counter=\processor(_total)\%%%% processor time" & rem english version

 typeperf "!counter!" -si %1  | cmd /V:ON /C "@echo off&set S=_,.-ùïî&set Bcpu=K&for /F %%a in ('findstr ","') do (set v=%%a&if defined v (set cpu=!v:*,=!&set cpu=  !cpu:~1,-6!&(set /a i=!cpu:~0,-2!*6/100)>nul&for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)&set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!))"

goto :eof


but is blocked , nothing appear

but this work : typeperf "!counter!" -si %1 | findstr ","

what do you mean with "parse the data to lines" . I have undestand the problem with set /p .
But I don't know what do findstr in this case.

Einstein1969

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#6 Post by penpen » 01 Dec 2013 17:46

einstein1969 wrote:...
but is blocked , nothing appear
Curious thing, that the above does not work as i expect... with "type typeperf.txt | ..." it works without problems on my WinXP home... .
I fear, that i have to test it on a system with typeperf (may take a while).

einstein1969 wrote:what do you mean with "parse the data to lines" . I have undestand the problem with set /p .
But I don't know what do findstr in this case.
With "parse the data to lines" i wanted to say you have to reconstruct the text lines on the receiver side of the pipe (sender | receiver).

The program findstr searches for pattern of texts linewise, so it reconstructs the lines, and if using within a "for/F" loop the reconstructed lines are assigned to the loop variable(s) if specified.

penpen

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#7 Post by penpen » 01 Dec 2013 17:56

Right now, i see an error in my above post... "tokens=* delims=" is missing in the for loop i have posted..., sry for that (and the type command is wrong, too).
With some good luck this may be the reason for the lock.
So this should be the corrected line:

Code: Select all

typeperf "!counter!" -si %1 | cmd /V:ON /C "@echo off&set S=_,.-ùïî&set Bcpu=K&for /F "tokens=* delims=" %%a in ('findstr ","') do (set v=%%a&if defined v (set cpu=!v:*,=!&set cpu=  !cpu:~1,-6!&(set /a i=!cpu:~0,-2!*6/100)>nul&for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)&set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!))"

penpen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: CPU History on title

#8 Post by einstein1969 » 01 Dec 2013 18:56

penpen wrote:Right now, i see an error in my above post... "tokens=* delims=" is missing in the for loop i have posted..., sry for that (and the type command is wrong, too).
With some good luck this may be the reason for the lock.
So this should be the corrected line:

Code: Select all

typeperf "!counter!" -si %1 | cmd /V:ON /C "@echo off&set S=_,.-ùïî&set Bcpu=K&for /F "tokens=* delims=" %%a in ('findstr ","') do (set v=%%a&if defined v (set cpu=!v:*,=!&set cpu=  !cpu:~1,-6!&(set /a i=!cpu:~0,-2!*6/100)>nul&for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)&set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!))"

penpen


I don't try this because is late. I will tomorrow. But the question is:

findstr wait that the stream in input ending before processing?

The initial script launch typeperf in an endless mode.

I'm looking a long time for a method that processing the input while the output is generated. But seem the alternative is using only set /p :(

I search this method for interprocess communication for parallel processing sync too.

Einstein1969

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#9 Post by penpen » 02 Dec 2013 06:35

einstein1969 wrote:...
But the question is:

findstr wait that the stream in input ending before processing?

The initial script launch typeperf in an endless mode.

I'm looking a long time for a method that processing the input while the output is generated. But seem the alternative is using only set /p :(

I search this method for interprocess communication for parallel processing sync too.
Yes, findstr is buffering data before it displays it.
Normally this may be fixed using find, but the "for /F" loop seems to buffer, too.

Code: Select all

Z:\>(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul
2>nul)&echo 4,&echo 5,& echo 6,) | (@echo off&find /N ",")

versus

Z:\>(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul
2>nul)&echo 4,&echo 5,& echo 6,) | (@echo off&for /F %a in ('find /N ","') do ec
ho %a)
You may be forced to use a batch at the receiver side of the pipe with a goto loop and "set/P", if "for /L" is buffering, too.
AND it looks like there is a problem using "for /L"/"set/P" :evil: :

Code: Select all

Z:\>(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul
2>nul)&echo 4,&echo 5,& echo 6,) | cmd /V:ON /C "(@echo off&for /L %a in (1,1,20
) do (set v=&set /P v=&echo [%a]!v!))"
[1]1,
[2]4,
[3]5,
[4]!v!
[5]!v!
[6]!v!
[7]!v!
[8]!v!
[9]!v!
[10]!v!
[11]!v!
[12]!v!
[13]!v!
[14]!v!
[15]!v!
[16]!v!
[17]!v!
[18]!v!
[19]!v!
[20]!v!

penpen

Edited: Corrected the "for /L"/"set/P" problem.
Last edited by penpen on 02 Dec 2013 07:55, edited 1 time in total.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#10 Post by penpen » 02 Dec 2013 07:51

Additionally: Sad to say that set /P seems to have problems with pipes, when any line ending character is involved, so you have to reformat the data (replace the newlines, carriage returns) before sending it to the pipe.

If you would replace the line end chars by a '#' and avoid '=' chars, then this is a simple piping and line reconstructing example:

Code: Select all

::source.bat
@echo off
setlocal
for %%a in (a b c d e # f g h i j # k l m n o p #) do <nul set /p "=%%a"
for %%a in (a b c d e f g #) do <nul set /p "=%%a"
for %%a in (h i j k l m n o p #) do <nul set /p "=%%a"
<nul set /p "=q"
endlocal

Code: Select all

::pipeOut.bat
@echo off
cls
   setlocal enableDelayedExpansion
   echo:%0: started
   set "buffer="
   set "line="
   set "endOfStream=q"
:readkey
   set "input="
   set /p "input="
   if DEFINED input goto :inputAvailable
   goto :readkey

:inputAvailable
   set "buffer=%buffer%%input%"

   echo:%0: input="%input%",   buffer="%buffer%"
   
:detectLine
   if not defined buffer goto :noBuffer
   set "line=%buffer:*#=%"
   if defined line (
      set "line=!buffer:%line%=!"
   ) else (
      set "line=%buffer%"
   )
   if defined line (
      set "buffer=%buffer:*#=%"
      echo line found: "%line:~0,-1%", buffer="!buffer!"
      goto :detectLine
   )

:noBuffer
   set "isEndOfStream=!input:%endOfStream%=%endOfStream%_!"
   if %input% == %isEndOfStream% goto :readkey
   echo:%0: leaving
   endlocal

penpen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: CPU History on title

#11 Post by einstein1969 » 02 Dec 2013 08:56

penpen wrote:
einstein1969 wrote:...
But the question is:

findstr wait that the stream in input ending before processing?

The initial script launch typeperf in an endless mode.

I'm looking a long time for a method that processing the input while the output is generated. But seem the alternative is using only set /p :(

I search this method for interprocess communication for parallel processing sync too.
Yes, findstr is buffering data before it displays it.
Normally this may be fixed using find, but the "for /F" loop seems to buffer, too.

Code: Select all

Z:\>(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul
2>nul)&echo 4,&echo 5,& echo 6,) | (@echo off&find /N ",")

versus

Z:\>(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul
2>nul)&echo 4,&echo 5,& echo 6,) | (@echo off&for /F %a in ('find /N ","') do ec
ho %a)
You may be forced to use a batch at the receiver side of the pipe with a goto loop and "set/P", if "for /L" is buffering, too.
AND it looks like there is a problem using "for /L"/"set/P" :evil: :

Code: Select all

Z:\>(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul
2>nul)&echo 4,&echo 5,& echo 6,) | cmd /V:ON /C "(@echo off&for /L %a in (1,1,20
) do (set v=&set /P v=&echo [%a]!v!))"
[1]1,
[2]4,
[3]5,
[4]!v!
[5]!v!
[6]!v!
[7]!v!
[8]!v!
[9]!v!
[10]!v!
[11]!v!
[12]!v!
[13]!v!
[14]!v!
[15]!v!
[16]!v!
[17]!v!
[18]!v!
[19]!v!
[20]!v!

penpen

Edited: Corrected the "for /L"/"set/P" problem.


the problem seem not the FOR /L

Code: Select all

(echo 1,&echo 2,& echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul2>nul)&echo 4,&echo 5,& echo 6,) | cmd /V:ON /C "(@echo off&set v=&set /P v=&echo [1]!v!&set v=&set /P v=&echo [2]!v!&set v=&set /P v=&echo [3]!v!&set v=&set /P v=&echo [4]!v!&set v=&set /P v=&echo [5]!v!&set v=&set /P v=&echo [6]!v!&set v=&set /P v=&echo [7]!v!&set v=&set /P v=&echo [8]!v!)"
[1]1,
[2]4,
[3]5,
[4]6,
[5]!v!
[6]!v!
[7]!v!
[8]!v!


Einstein1969

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: CPU History on title

#12 Post by einstein1969 » 02 Dec 2013 10:13

penpen wrote:Additionally: Sad to say that set /P seems to have problems with pipes, when any line ending character is involved, so you have to reformat the data (replace the newlines, carriage returns) before sending it to the pipe.

If you would replace the line end chars by a '#' and avoid '=' chars, then this is a simple piping and line reconstructing example:

Code: Select all

::source.bat
@echo off
setlocal
for %%a in (a b c d e # f g h i j # k l m n o p #) do <nul set /p "=%%a"
for %%a in (a b c d e f g #) do <nul set /p "=%%a"
for %%a in (h i j k l m n o p #) do <nul set /p "=%%a"
<nul set /p "=q"
endlocal

Code: Select all

::pipeOut.bat
@echo off
cls
   setlocal enableDelayedExpansion
   echo:%0: started
   set "buffer="
   set "line="
   set "endOfStream=q"
:readkey
   set "input="
   set /p "input="
   if DEFINED input goto :inputAvailable
   goto :readkey

:inputAvailable
   set "buffer=%buffer%%input%"

   echo:%0: input="%input%",   buffer="%buffer%"
   
:detectLine
   if not defined buffer goto :noBuffer
   set "line=%buffer:*#=%"
   if defined line (
      set "line=!buffer:%line%=!"
   ) else (
      set "line=%buffer%"
   )
   if defined line (
      set "buffer=%buffer:*#=%"
      echo line found: "%line:~0,-1%", buffer="!buffer!"
      goto :detectLine
   )

:noBuffer
   set "isEndOfStream=!input:%endOfStream%=%endOfStream%_!"
   if %input% == %isEndOfStream% goto :readkey
   echo:%0: leaving
   endlocal

penpen


umh, this is work for only one line?

I need that work for a variable number of lines. :(

Other question on this type of working is :

How to detect CR or LF or the pair in any order and trasform it?

In the mini-monitor i have found a solution that use two trick : 1) use of start, 2 use of more

Seem that cmd versus start is the difference for working set /p a little better

The other important question is :

why this is more stable?

Code: Select all

>start "" /B cmd /c "echo 1,&echo 2,&echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul2>nul)&echo 4,&echo 5,& echo 6," | cmd /V:ON /c "@echo off&for /L %a in (1,1,2000) do (set v=&set /P v=&if defined v echo [%a]!v!)"
[1]1,
[2]2,
[3]3,
[4]pause,
[5]4,
[6]5,
[7]6,


EDIT: This work with /WAIT also

Einstein1969

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#13 Post by penpen » 02 Dec 2013 10:40

einstein1969 wrote:umh, this is work for only one line?

I need that work for a variable number of lines. :(
It is for a variable number of line, but it is transmitted as one line:
source text file wrote:line 1
line 2
...
line n
coded source text file to send it through the pipe wrote:line1#line2#...#linen#q
You may transmit any number of lines you want, you just have to avoid using '#', 'q', '=', NL, CR, and some problematic control characters, i assume. (should all not be in the typeperf output, if i see it right).

einstein1969 wrote:The other important question is :

why this is more stable?

Code: Select all

>start "" /B cmd /c "echo 1,&echo 2,&echo 3,&echo pause,&((ping 192.168.0.10 -n 1 -w 5000)>nul2>nul)&echo 4,&echo 5,& echo 6," | cmd /V:ON /c "@echo off&for /L %a in (1,1,2000) do (set v=&set /P v=&if defined v echo [%a]!v!)"
[1]1,
[2]2,
[3]3,
[4]pause,
[5]4,
[6]5,
[7]6,


EDIT: This work with /WAIT also
Although this indeed seems to be more stable on my WinXP home, this sometimes return wrong results, too:

Code: Select all

Z:\>start "" /B cmd /c "echo 1,&echo 2,&echo 3,&echo pause,&((ping 192.168.0.10
-n 1 -w 5000)>nul2>nul)&echo 4,&echo 5,& echo 6," | cmd /V:ON /c "@echo off&for
/L %a in (1,1,2000) do (set v=&set /P v=&if defined v echo [%a]!v!)"
[1]1,
[2]2,
[3]4,
[4]5,

penpen

Edit: Added 'q' to the forbidden characters.
Last edited by penpen on 02 Dec 2013 11:06, edited 1 time in total.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: CPU History on title

#14 Post by penpen » 02 Dec 2013 11:02

I've just got a flash of inspiration, but it will only work, if you are able to make typeperf to output only one measured value:

Code: Select all

:: reserved file name, is not allowed to contain any space: "abort.txt"
set abort=abort.txt
if exist %abort% echo Unexpected critical error: Reserved file "%abort%" is in use.&goto :eof
copy nul %abort% /Y
:loop
if not exist %abort% goto :eof
@echo off
set S=_,.-ùïî
set Bcpu=K
for /F "tokens=* delims=" %%a in ('type typeperfOne.txt  ^| findstr ","') do (
   set v=%%a
   if defined v (
      set cpu=!v:*,=!
      set cpu=  !cpu:~1,-6!
      (set /a i=!cpu:~0,-2!*6/100)>nul
      for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)
      set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!
   )
)
goto :loop
You only have to replace "type typeperfOne.txt" with the typeperf command that only forces one measure value.
This way it costs some more performance, but it should work.
The endless loop is breaked, if you delete the file specified by the variable abort.
The main advantage: Much more readable :D .

penpen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: CPU History on title

#15 Post by einstein1969 » 03 Dec 2013 05:04

penpen wrote:I've just got a flash of inspiration, but it will only work, if you are able to make typeperf to output only one measured value:

Code: Select all

:: reserved file name, is not allowed to contain any space: "abort.txt"
set abort=abort.txt
if exist %abort% echo Unexpected critical error: Reserved file "%abort%" is in use.&goto :eof
copy nul %abort% /Y
:loop
if not exist %abort% goto :eof
@echo off
set S=_,.-ùïî
set Bcpu=K
for /F "tokens=* delims=" %%a in ('type typeperfOne.txt  ^| findstr ","') do (
   set v=%%a
   if defined v (
      set cpu=!v:*,=!
      set cpu=  !cpu:~1,-6!
      (set /a i=!cpu:~0,-2!*6/100)>nul
      for %%b in (!i!) do @(set Bcpu=!Bcpu!!S:~%%b,1!)
      set Bcpu=!Bcpu:~-30!&title CPU:!cpu:~-5!%%  !Bcpu!
   )
)
goto :loop
You only have to replace "type typeperfOne.txt" with the typeperf command that only forces one measure value.
This way it costs some more performance, but it should work.
The endless loop is breaked, if you delete the file specified by the variable abort.
The main advantage: Much more readable :D .

penpen


For me, unfortunately, one of the requirements for an application that monitors the cpu usage is to use little CPU and few processes. Anyway, thank you for giving a more readable form. The insert in the first post stands out as before.

Einstein1969

Post Reply