невозможно получить ответ арифметического расчета в пакетном сценарии

Я пытаюсь получить процент использования памяти для конкретного PID процесса, но печатаются только значения, а не выходное значение расчета.

@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%

Я новичок в пакетном скриптинге. Я что-то упускаю?


comment
Вы делите КБ на байты.   -  person dxiv    schedule 11.06.2020
comment
Используйте set /a для арифметических функций. См. ss64.com/nt/set.html#expressions.   -  person Nico Nekoru    schedule 11.06.2020
comment
Я не уверен, что вы берете значение памяти из соответствующего места. Процесс не использует процент вашей физической памяти, он использует процент вашей виртуальной памяти, то есть памяти, которую система выделяет для запуска программных приложений. Чтобы получить это значение, должно быть относительно небольшое изменение, wmic computersystem get TotalPhysicalMemory /valueWMIC OS Get TotalVirtualMemorySize /value.   -  person Compo    schedule 11.06.2020
comment
Н. Б.: Неуравновешенные скобки…   -  person aschipfl    schedule 11.06.2020
comment
На самом деле вам не нужны группировки для команды SET. Он следует тем же правилам, которым вы научились в начальной школе, в том, что касается порядка операций.   -  person Squashman    schedule 12.06.2020
comment
@NekoMusume Я удалил круглые скобки и добавил /A в SET ... set /A MEM=%%F*100 /%%a, но не получил ожидаемого результата, а также получил ошибку ниже: Неверный номер. Числа ограничены 32-битной точностью. Процент памяти = 3   -  person A1229    schedule 12.06.2020
comment
@Compo, спасибо за информацию, изменю wmic...   -  person A1229    schedule 12.06.2020


Ответы (1)


Основываясь на совете, который я дал в своем комментарии, и используя другой метод определения процесса, связанного с PID, вы можете сделать это следующим образом: (при необходимости изменить PID, 5716, в строке 2):

@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

Обратите внимание, однако, что если арифметика встретит числа, которые превышают ограничение Set /A для 32-битных целых чисел со знаком, метод завершится ошибкой. Кроме того, вы должны отметить, что поскольку мы работаем с целыми числами, результат всегда будет округляться в меньшую сторону до ближайшего целого числа. Это означает, что все, что меньше 1%, будет отображаться как 0%.

Если я правильно помню, при первом использовании этого метода в любом сеансе возникает задержка, после которой вы обычно заметите значительное увеличение скорости.


Если вы уже знаете имя процесса, которое обычно является именем исполняемого файла без его расширения, тогда вы можете использовать его вместо PID, (при необходимости измените строку ExecutableFile в строке 2 на имя вашего процесса):

@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
person Compo    schedule 12.06.2020