Почему этот код не работает?
Пожалуйста, прочитайте этот ответ для получения подробной информации о командах SETLOCAL и ENDLOCAL . При использовании SETLOCAL внутри цикла FOR настоятельно рекомендуется также использовать ENDLOCAL в том же цикле FOR , иначе во время переполнения стека выполнение цикла. Это не происходит здесь, потому что не так много итераций цикла, но все же следует использовать ENDLOCAL в том же цикле FOR , содержащем также SETLOCAL .
For %%# in (*) do
в коде вопроса обрабатывает каждое имя файла не скрытых файлов в текущем каталоге. Имя файла без расширения файла присваивается переменной среды var
. Затем эта переменная присваивается другой переменной MyVar
без каких-либо изменений, за исключением того, что строка Set MyVar=!var!
будет содержать конечные пробелы или символы табуляции. И наконец, все пробелы удаляются из строкового значения переменной окружения MyVar
, которая является именем файла.
Понятия не имею, что этот цикл FOR для обработки имен файлов в текущем каталоге связан с именем видеоконтроллера и текущим разрешением по горизонтали и вертикали.
Я рекомендую прочитать ответ на Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке?
Закрывающая круглая скобка )
в командной строке echo %%a (%%b x !MyVar!)>>"GPU.txt"
интерпретируется как конец командного блока первого FOR . Необходимо было бы экранировать )
с помощью ^
и использовать echo %%a (%%b x !MyVar!^)>>"GPU.txt"
, чтобы получить закрывающую скобку, интерпретируемую cmd.exe
как буквальный символ, для вывода с помощью echo
при разборе всего блока команд, начиная с (
на первом FOR командная строка.
wmic.exe
выводит текст UTF-16 Little Endian (два байта на символ) вместо кодированного ANSI (один байт на символ). FOR соответственно cmd.exe
имеет ошибку при интерпретации потока символов в кодировке Unicode, как подробно объяснено, например, в Как исправить неправильное поведение при перезаписи переменных при разборе вывода?
То, что вы считаете пробелом в конце значения вертикального разрешения, в действительности означает возврат каретки, добавленный к этому значению из-за неправильной обработки Unicode-вывода wmic.exe
командой FOR соответственно cmd.exe
.
Что такое рабочий код и почему он работает?
Одним из возможных решений этой задачи является использование этого кода пакета:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(for /F "tokens=2-4 delims=," %%I in ('%SystemRoot%\System32\wbem\wmic.exe PATH Win32_VideoController GET Caption^,CurrentHorizontalResolution^,CurrentVerticalResolution /FORMAT:CSV ^| %SystemRoot%\System32\findstr.exe /R ",[0123456789][0123456789]*$"') do (
set /A CurrentVerticalResolution=%%K
call echo %%I (%%J x %%CurrentVerticalResolution%%^)
))>"GPU.txt"
endlocal
Вывод Unicode команды инструментария управления Windows перенаправляется на FINDSTR , который фильтрует вывод в строках, заканчивающихся запятой и одной или несколькими цифрами. Таким образом, строка заголовка выхода CSV удаляется, а также строки видеоконтроллера, заканчивающиеся ,,
без значений для текущего разрешения по горизонтали и вертикали. Такая строка CSV выводится также на моем компьютере с Windows в дополнение к строке CSV с правильными значениями.
Проблема с неправильным возвратом каретки в конце последнего значения текущего вертикального разрешения остается, несмотря на фильтрацию вывода wmic.exe
с findstr.exe
.
По этой причине текущее значение вертикального разрешения, назначенное переменной цикла K
, не используется напрямую в командной строке echo
, поскольку это приведет к )
перезаписи первого символа строки заголовка видеоконтроллера. Используемое здесь решение использует арифметическое выражение для присвоения текущего значения разрешения по вертикали переменной окружения CurrentVerticalResolution
. Возврат каретки в конце целочисленного значения интерпретируется как любой другой символ пробела в конце выражения при вычислении арифметического выражения, что означает, что оно игнорируется cmd.exe
. Таким образом, переменная окружения CurrentVerticalResolution
присвоила значение без нежелательного возврата каретки в конце.
Приведенный выше код позволяет избежать использования SETLOCAL и ENDLOCAL с помощью команды CALL для двойного анализа командной строки echo
, как объяснено:
Как интерпретатор сценариев Windows Command Interpreter (CMD.EXE) анализирует?
Командная строка echo
с экранированным )
и %%CurrentVerticalResolution%%
вместо %CurrentVerticalResolution%
уже изменено на строку ниже при первом разборе командной строки echo
на cmd.exe
перед выполнением команды FOR :
call echo %I (%J x %CurrentVerticalResolution%)
Замена оставшейся ссылки на переменную окружения %CurrentVerticalResolution%
замененапо текущему значению этой переменной среды перед выполнением команды ECHO при втором разборе на каждой итерации цикла из-за команды CALL .
Можно также использоватьвнутри цикла FOR :
setlocal EnableDelayedExpansion
echo %%I (%%J x !CurrentVerticalResolution!^)
endlocal