0

I am trying to get Percentage Memory usage of a particular process PID, but only values are getting printed and not the calculation output value.

@echo off

setlocal enableextensions EnableDelayedExpansion

set PID=5716

for /f "tokens=5 delims= " %%F in ('tasklist /nh /FI "PID eq !PID!"') do (
   for /f "tokens=2 delims==" %%a in ('wmic computersystem get TotalPhysicalMemory /value')  do (
          set "MEM=((%%F*100) /%%a)"

    )
    )
    )
echo PercentageMemory = %MEM%

I am new to batch scripting. Am I missing something?

James Z
  • 12,209
  • 10
  • 24
  • 44
A1229
  • 1
  • 1
  • 1
  • 2
  • You are dividing KB by bytes. – dxiv Jun 11 '20 at 19:12
  • 1
    Use `set /a` for arithmetic functions. See https://ss64.com/nt/set.html#expressions – Nico Nekoru Jun 11 '20 at 19:14
  • 1
    I'm not sre that you're taking your memory value from the appropriate place. A process isn't using a percentage of your physical memory, its using a percentage of your virtual memory, i.e. the memory which the system sets aside for running software applications. To retrieve that value, should be a relatively small change, `wmic computersystem get TotalPhysicalMemory /value` → `WMIC OS Get TotalVirtualMemorySize /value`. – Compo Jun 11 '20 at 19:49
  • *N. B.:* There are unbalanced parentheses… – aschipfl Jun 11 '20 at 20:55
  • In reality you don't need the groupings for the `SET` command. It follows the same rules you learned in elementary school as far as order of operations. – Squashman Jun 11 '20 at 21:56
  • @NekoMusume I removed parentheses and added /A in SET ... "set /A MEM=%%F*100 /%%a" but not getting expected output and also getting below error: Invalid number. Numbers are limited to 32-bits of precision. PercentageMemory = 3 – A1229 Jun 12 '20 at 05:26
  • @Compo thanks for the info, Will modify the wmic... – A1229 Jun 12 '20 at 05:29

1 Answers1

0

Based upon the advice I provided in my comment, and using a different method of determining the process associated with the PID, you could do it like this, (change the PID, 5716, on line 2 as necessary):

@SetLocal EnableExtensions
@Set "PID=5716"
@Set "$Mem="
@For /F "Tokens=2 EOL=N Delims=," %%G In (
    '%__AppDir__%wbem\WMIC.exe OS Get TotalVirtualMemorySize^,Version^
     /Format:CSV 2^>NUL')Do @For /F "Tokens=2 EOL=N Delims=," %%H In (
    '%__AppDir__%wbem\WMIC.exe Path Win32_PerfFormattedData_PerfProc_Process^
     Where "IDProcess='%PID%'" Get WorkingSet^,WorkingSetPrivate /Format:CSV^
     2^>NUL')Do @Set /A "$Mem=%%H/1024*100/%%G">NUL 2>&1
@If Defined $Mem Echo %$Mem%%%&Pause

Please note however, that if the arithmetic meets numbers which exceed the Set /A limitation of 32-bit signed integers, the method will fail. Also, you should note that because we're working with integers, the result will always be rounded down to the nearest integer. This means anything below 1% will show as 0%

If I remember correctly, there is a delay when you use this method for the first time in any session, after that, you'll usually notice a significant speed increase.


If you already know the name of the process, which is usually the name of the executable without its extension, then you could use that instead of the PID, (change the ExecutableFile string on line 2 to your process name as necessary):
@SetLocal EnableExtensions
@Set "MyProcess=ExecutableFile"
@Set "$Mem="
@For /F "Tokens=2 EOL=N Delims=," %%G In (
    '%__AppDir__%wbem\WMIC.exe OS Get TotalVirtualMemorySize^,Version^
     /Format:CSV 2^>NUL')Do @For /F "Tokens=2 EOL=N Delims=," %%H In (
    '%__AppDir__%wbem\WMIC.exe Path Win32_PerfFormattedData_PerfProc_Process^
     Where "Name='%MyProcess%'" Get WorkingSet^,WorkingSetPrivate /Format:CSV^
     2^>NUL')Do @Set /A "$Mem=%%H/1024*100/%%G">NUL 2>&1
@If Defined $Mem Echo %$Mem%%%&Pause
Compo
  • 36,585
  • 5
  • 27
  • 39