Я хочу обрабатывать разные функции в зависимости от общего объема оперативной памяти ПК.
Для этого я придумал эту функцию:
:function.texture_streaming
setlocal EnableDelayedExpansion
for /f "usebackq tokens=*" %%a in (
`PowerShell -Command "(Get-WmiObject Win32_PhysicalMemory | Measure Capacity -Sum).Sum/1GB"`
) do (
set "ram=%%a"
)
if "%ram%" lss "16" (
call :error.insufficient_ram "!ram!"
endlocal
goto :prompt.performance
)
if "%ram%" geq "16" if "%ram%" lss "32" (
call :subroutine.limited_texture_streaming
endlocal
goto :prompt.performance
)
if "%ram%" geq "32" (
call :subroutine.full_texture_streaming
endlocal
goto :prompt.performance
)
endlocal
goto :prompt.performance
Моя проблема в том, что независимо от значения %ram%
всегда обрабатывается последний оператор if. Даже если я установлю значение %ram%
на 8
вручную, он все равно обработает последний оператор if, когда мне нужно обработать первый. Я также перенаправил значение %ram%
в текстовый файл, чтобы проверить, есть ли пробелы, но их нет.
Еще несколько предложений: замените весь командный блок for /f
одной командной строкой for /F %%I in ('%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -Command "(Get-WmiObject Win32_PhysicalMemory | Measure Capacity -Sum).Sum/1GB"') do set "ram=%%I"
. Расширение отложенной переменной вообще не требуется. Замените setlocal EnableDelayedExpansion
на setlocal EnableExtensions DisableDelayedExpansion
или удалите эту строку и все endlocal
и, конечно же, замените call :error.insufficient_ram "!ram!"
на call :error.insufficient_ram "%ram%"
.
Я бы посоветовал вам изменить команду, чтобы использовать командлет CIM, а не WMI. Вот без сокращений: For /F %%G In ('%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -Command "(Get-CimInstance Cim_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB" 2^>NUL') Do Set "ram=%%G"
.
@Mofi Я прочитал упомянутый вами ответ и соответствующим образом скорректировал другие части моего сценария. Я не знал, что equ
отличается от ==
. Я также исключил из кавычек переменную и целочисленное значение в каждом операторе if
, и это помогло! @Compo Я перешел на CIM
вместо WMI
, как вы предлагали. Спасибо вам обоим за ваши предложения и помощь.
На самом деле вам не требуется установка переменной, вам не нужны все внутренние круглые скобки и не требуется delayedexpansion
.
Вы можете просто выполнить поиск, используя метапеременную %%a
.
:function.texture_streaming
for /f "delims = " %%a in ('PowerShell -Command "(Get-WmiObject Win32_PhysicalMemory | Measure Capacity -Sum).Sum/1GB"') do (
if %%a lss 16 call :error.insufficient_ram %%a
if %%a geq 16 if %%a lss 32 call :subroutine.limited_texture_streaming
if %%a geq 32 call :subroutine.full_texture_streaming
goto :prompt.performance
)
Кроме того, вам не нужен goto :prompt.performance
после каждого оператора if
, так как все несовпадающие операторы if будут провалены и все они достигнут goto
после последнего if
.
Герхард, возможно, вы и правы насчет использования отложенного раскрытия, но вполне возможно, что оно требуется где-то в неопубликованных разделах с пометками :error.insufficient_ram
, :subroutine.limited_texture_streaming
и :subroutine.full_texture_streaming
.
Это действительно возможно, @Compo, но я почти уверен, что OP установил отложенное расширение из-за расширения, необходимого для переменной !ram!
в цикле for. Однако ОП может добавить его обратно, если это необходимо.
Благодаря @Mofi и @Compo мне удалось решить проблему.
Это теперь работающий код:
setlocal
rem Initialize variable.
set "ram = "
for /f "usebackq tokens=*" %%a in (
`PowerShell -NoLogo -NoProfile -Command "(Get-CIMInstance CIM_PhysicalMemory | Measure-Object -Property Capacity -Sum).Sum / 1GB"`
) do (
set "ram=%%a"
)
if not defined ram (
call :error.function_failed "determining your total RAM capacity"
endlocal
goto :prompt.performance
)
if %ram% lss 16 (
pause
call :error.insufficient_ram "%ram%"
endlocal
goto :prompt.performance
)
if %ram% geq 16 if %ram% lss 32 (
call :subroutine.limited_texture_streaming
endlocal
goto :prompt.performance
)
if %ram% geq 32 (
call :subroutine.full_texture_streaming
endlocal
goto :prompt.performance
)
endlocal
goto :prompt.performance
Пожалуйста, прочитайте мой ответ на Символ, эквивалентный NEQ, LSS, GTR и т. д. в пакетных файлах Windows. Использование
"
в условии IF всегда приводит к сравнению строк, а не к целочисленному сравнению, как вам хотелось бы. Используйтеif %ram% LSS 16
,if %ram% GEQ 16 if %ram% LSS 32
иif %ram% GEQ 32
. Следует убедиться, что с помощьюset "ram = "
вверху иif not defined ram goto :EOF
после цикла FOR /F необходимо убедиться, что эта переменная среды вообще может быть успешно определена с помощью 32-битного целочисленного значения со знаком.