Вызов `ver` в выражении FOR из командного файла останавливает cmd в Windows 10 - PullRequest
2 голосов
/ 01 октября 2019

Я пытаюсь проверить версию ОС из командного файла и сталкиваюсь со следующей проблемой.

Строка

FOR /F "tokens=*" %%i IN ('ver') DO (SET var=%%i)

остановит cmd при выполнении из командного файлав то время как сама команда ver (в том же пакетном файле) выполняется без проблем. (ver имеет следующий вывод.)

Microsoft Windows [Version 10.0.18362.356]

Что может быть неправильным в выражении?

Ответы [ 4 ]

1 голос
/ 02 октября 2019

Чтобы избежать рекурсии и неожиданного поведения FOR / F, вы можете использовать защиту в пакетном скрипте AutoRun (например, переменная на основе , показанная @sst).

@echo off
setlocal EnableDelayedExpansion
set "cmd=!cmdcmdline!"

if "!cmd!" == "!cmd:/=!" (
    REM *** Define doskey macros
    2>nul (
      doskey npp="%ProgramFiles(x86)%\notepad++\notepad++.exe" $*
    )

    endlocal

    REM *** Set additional variables

    REM *** Change to a default directory
    cd c:\temp
)
1 голос
/ 02 октября 2019

Как уже упоминалось в комментариях под вашим вопросом, очевидное зависание вызвано тем, что вы настроили команду cmd для выполнения через параметр реестра AutoRun команды cmd: [HKEY_LOCAL_MACHINE/HKEY_CURRENT_USER]\Software\Microsoft\Command Processor\AutoRun

При использовании for /F для захвата выходных данных другой команды / программы будет вызываться неявный экземпляр cmd для выполнения команды / программы, указанной в предложении IN for.

Когда естьэто запись в параметре реестра AutoRun команды cmd, которая в свою очередь неявный экземпляр cmd будет выполнять команды AutoRun, а в вашем случае эта команда AutoRun выполнит другой экземпляр cmd с помощью команды for /F,Вы видите, что это происходит: бесконечная цепочка вложенных cmd s будет запускаться до тех пор, пока она не исчерпает системные ресурсы.

Чтобы избежать захвата в бесконечном цикле, необходимо защитить оператор от многократного выполнения

Вот один метод, который записан в виде пакетного файла:

:: This batch file can be safely executed through cmd's Autorun

@echo off
if not defined WinVer (
    set "WinVer=AutorunGuard"
    for /F "tokens=1* delims=[" %%A in ('ver') do (
        for /F "tokens=2 delims=] " %%V in ("%%B") do set "WinVer=%%V"
    )
)

Я также расширил метод извлечения версии Windows, включив в нее только номер версии, а не всю строку версии. который возвращается ver
Может использоваться для извлечения номера версии для версий Windows из Windows 2000 в Windows 10

Если вы не хотите использовать пакетный файл и предпочитаете поставитьоператор переходит в AutoRun параметр реестра, этот однострочный можно использовать вместо:

@if not defined WinVer set "WinVer=AutorunGuard" & for /F "tokens=1* delims=[" %A in ('ver') do @for /F "tokens=2 delims=] " %V in ("%B") do @set "WinVer=%V"
0 голосов
/ 01 октября 2019

Вы можете получить информацию из Win32_OperatingSystem, используя :

@For /F "EOL=V" %%A In ('WMIC OS Get Version')Do @For /F "Tokens=*" %%B In ("%%A")Do @Set "var=%%B"

или :

@For /F %%A In ('"PowerShell (GWMI Win32_OperatingSystem).Version"')Do @Set "var=%%A"

Вы также можете сделатьто же самое, используя , то есть используя один из или .


Альтернативой, хотя и не такой надежной, как при использовании WMI, является получение информации из реестра.
@Echo Off
Set "RKey=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
Set "KVal=\<CurrentBuildNumber\> \<CurrentVersion\> \<ProductName\> \<UBR\>"
For /F Tokens^=1-2* %%A In (
    '^""%__AppDir__%reg.exe" Query "%RKey%" 2^>NUL^|"%__AppDir__%findStr.exe" /I "%KVal%"^"'
)Do @If "%%A"=="UBR" (Set /A %%A=%%C)Else Set "%%A=%%C"
Echo(%ProductName% %CurrentVersion%.%CurrentBuildNumber%.%UBR%
Pause

Примечание. Я не думаю, что UBR является записью, предшествующей Windows 7, поэтомув этих случаях у вас просто будет конечный период в выходных данных.

0 голосов
/ 01 октября 2019

Не называйте ваш пакетный файл как ver.bat ;Например, переименуйте его в CMD_Version.bat

@echo off
FOR /F "tokens=*" %%i IN ('ver') DO (SET var=%%i)
echo %var%
pause
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...