CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Аватара пользователя
Lucretius

CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Lucretius »

Включил в батник следующие строки:



Код:

Код: Выделить всё

For /F "Tokens=2,*" %%i In ('2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{*-*-*-*-*}_is1" /V InstallLocation') Do if /i "%%j" neq "%~dp0" Goto label

скрипт сверяет путь взятый из реестра с директорией расположения батника. Оказалось, что оператор сравнения "neq" не работает(при тождестве "%%j" и "%~dp0" происходит переход по метке) в данном скрипте на WinXP, причём c оператором "equ" скрипт работает правильно. На Win7 ОБА варианта работают правильно.



Помогите разобраться с чем это может быть связано.
Аватара пользователя
Lucretius

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Lucretius »

Если включить в скрипт конструкции:



Код:

Код: Выделить всё

Do if "%%j"=="%~dp0" Goto label
REM или
Do if not "%%j"=="%~dp0" Goto label

наблюдается ситуация аналогичная вышеописанной.



На WinXP с оператором "neq" скрипт работает, только так:

Код:

Код: Выделить всё

For /F "Tokens=2,*" %%i In ('2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{*-*-*-*-*}_is1" /V InstallLocation') Do set Location=%%j
if /i "%Location%" neq "%~dp0" Goto label

Может кто сталкивался с подобной ситуацией?
Аватара пользователя
Lucretius

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Lucretius »

Lucretius, у Вас изначально ошибка — в алгоритме. В запросе «reg.exe /query» Вы получаете (или не получаете) несколько строк. Вам нужно отфильтровать среди них потребную:



Код:

Код: Выделить всё

@echo off
setlocal enableextensions enabledelayedexpansion
for /f "usebackq tokens=3 delims=	" %%i in (
	`reg.exe query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1E8BAA74-62A9-421D-A61F-164C7C3943E9}_is1" /v "InstallLocation" ^| find.exe /i "InstallLocation"`
) do set sInstallLocation=%%~i
if defined sInstallLocation echo [%sInstallLocation%]
endlocal
exit /b 0

Версии «reg.exe» под Windows XP и Windows 7 могут отдавать разную информацию, проверяйте.
Аватара пользователя
Iska

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Iska »

Lucretius, у Вас изначально ошибка — в алгоритме. В запросе «reg.exe /query» Вы получаете (или не получаете) несколько строк. Вам нужно отфильтровать среди них потребную:



Код:

Код: Выделить всё

@echo off
setlocal enableextensions enabledelayedexpansion
for /f "usebackq tokens=3 delims=	" %%i in (
	`reg.exe query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1E8BAA74-62A9-421D-A61F-164C7C3943E9}_is1" /v "InstallLocation" ^| find.exe /i "InstallLocation"`
) do set sInstallLocation=%%~i
if defined sInstallLocation echo [%sInstallLocation%]
endlocal
exit /b 0

Версии «reg.exe» под Windows XP и Windows 7 могут отдавать разную информацию, проверяйте.
Аватара пользователя
Georgio

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Georgio »

Lucretius, Вы, наверное, имели в виду, что при якобы очевидном тождестве "%%j" и "%~dp0" в условии IF "%%j" neq "%~dp0" всё равно происходит переход по метке. Ну, ладно, дело тут не в этом.



Вся проблема заключена в результате выполнения команды

Код:

Код: Выделить всё

REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*******" /V InstallLocation



Не знаю, как в других версиях утилиты reg.exe[/i], но у меня как в Windows XP, так и в Windows 7 результат выполнения команды, например,

Код:

Код: Выделить всё

REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{006B5C65-3938-4246-B182-994A7E415EDE}" /V InstallLocation

располагается в четыре строки:





Код:

Код: Выделить всё

                                                                                                                                                  
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{006B5C65-3938-4246-B182-994A7E415EDE}
    InstallLocation    REG_SZ    C:\Program Files\Intel\Bluetooth\

Первая и четвёртая строки -- пустые, командой FOR[/i] не обрабатываются. Отсюда следует, что команда FOR сначала должна "пройтись" по второй строке, а потом по третьей.



В указанном выше спучае при ключе "tokens=2*" второго и последующих "токенов" не найдётся, и переменные %%I и %%J не определятся. После этого будет обработана вторая строка, и переменная %%J примет ожидаемое нами значение C:\Program Files\Intel\Bluetooth\, после чего корректно выполнится условие IF.





Теперь рассмотрим другой случай.



Команда:

Код:

Код: Выделить всё

REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Download Master_is1" /V InstallLocation

Результат:

Код:

Код: Выделить всё

                                                                                                                                
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Download Master_is1
    InstallLocation    REG_SZ    C:\Program Files\Download Master\

В данном случае при том жк ключе "tokens=2*"[/i] команда FOR во второй (первой из непустых) строке "обнаружит" второй "токен" Master_is1, и явно декларированная переменная %%I примет его значение. А вот дальше нас ждёт "сюрприз"! Неявно объявленная переменная %%J, конечно не примет никакого значения, поскольку "токены" заканчиваются на втором, но (!) в условии IF эта переменная (точнее, "пустое место" от неё) фигурировать будет: IF /I "" NEQ "путь" GOTO label. Разумеется, что данное условие также будет выполнено корректно, и с переходом на метку прервётся цикл, так и не обработав третью (вторую из непустых), нужную нам, строку, в которой находится ожидаемое значение.





Третий пример.



Команда:

Код:

Код: Выделить всё

REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft .NET Framework 4 Client Profile" /V InstallLocation

Результат:

Код:

Код: Выделить всё

                                                                                                                                
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft .NET Framework 4 Client Profile
    InstallLocation    REG_SZ    C:\windows\Microsoft.NET\Framework\v4.0.30319\SetupCache\Client

Тут всё как в предыдущем примере, только переменная %%J[/i] уже определяется во второй (первой из непустых) строке и принимает значение Framework 4 Client Profile. Истинное условие "Framework 4 Client Profile" NEQ "путь" также срабатывает корректно, но ожидаемого результата мы не получаем, так как цикл снова обрывается после обработки второй (первой из непустых) строки.





Таким образом, в таких условиях получить правильный результат можно, только убрав вторую (первую из непустых) строку результата команды REG QUERY из обработки командой FOR, например, так:





Код:

Код: Выделить всё

FOR /F "skip=2 tokens=2*" %%I IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Download Master_is1" /V InstallLocation') DO IF /I "%%J" NEQ "%~dp0" GOTO label

Ключ "skip=2"[/i] -- это и есть пропуск двух первых строк при обработки командой FOR (в этом ключе в расчёт обязательно берутся и пустые строки).
Аватара пользователя
Georgio

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Georgio »

Iska, Ваш скрипт работает правильно только в случаях, когда в значении параметра InstallLocation отсутствуют пробелы. Поэтому надо так:





Код:

Код: Выделить всё

for /f "usebackq tokens=2* delims= " %%i in (
`reg.exe query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1E8BAA74-62A9-421D-A61F-164C7C3943E9}_is1" /v "InstallLocation" ^| find.exe /i "InstallLocation"`
) do set sInstallLocation=%%~j

И откуда-то в коде взялась табуляция...
Аватара пользователя
Georgio

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Georgio »

Цитата Georgio:



И откуда-то в коде взялась табуляция...
CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"




Она там и была. И именно табуляция. И именно потому команда «for /f» осуществляет разбор правильно, и под Windows XP в:


Цитата Georgio:



Iska, Ваш скрипт работает правильно только в случаях, когда в значении параметра InstallLocation отсутствуют пробелы. Поэтому надо так:
CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"




не было необходимости:


читать дальше »


Изображение



в отличие от более новых версий:


читать дальше »


Изображение



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



Я потому и писал:


Цитата Iska:



Версии «reg.exe» под Windows XP и Windows 7 могут отдавать разную информацию, проверяйте.
CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"





Цитата Georgio:



так это переведённая справка командной строки по операторам сравнения (Windows 7 Starter)
CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"




И в Windows 7 всё та же песня? Так и тянется четырнадцать лет?!
Аватара пользователя
Iska

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Iska »

Спасибо всем откликнувшимся!



Georgio Вы правы, я допустил опечатку, действительно

"при якобы очевидном тождестве "%%j" и "%~dp0" в условии IF "%%j" neq "%~dp0" всё равно происходит переход по метке."

(исправил в шапке)



Сразу скажу, что код на примере Вашего Iska:

Код:

Код: Выделить всё

For /f "usebackq Tokens=2*" %%I In (`2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /V "InstallLocation" ^| find.exe /i "InstallLocation"`) Do if /I "%%J\" NEQ "%~dp0" Goto label

и Ваш Georgio:

Код:

Код: Выделить всё

For /F "skip=2 Tokens=2*" %%I In ('2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /V InstallLocation') Do if /I "%%J\" NEQ "%~dp0" Goto label

работают правильно, как на WinXP так и на Win7.



По поводу знака табуляции - подтверждаю, работает на XP, но не работает на семёрке я поднимал уже эту тему
CMD/BAT - [решено] Значения параметров реестра в переменные.
.



Кстати, с пробелом в качестве разделителя:

Код:

Код: Выделить всё

for /f "usebackq tokens=2* delims= " %%i in (
`reg.exe query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /v "InstallLocation" ^| find.exe /i "InstallLocation"`
) do set sInstallLocation=%%~j

не работает на WinXP но работает на Win7, однако без указания разделителя:

Код:

Код: Выделить всё

for /f "usebackq tokens=2*" %%i in (
`reg.exe query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /v "InstallLocation" ^| find.exe /i "InstallLocation"`
) do set sInstallLocation=%%~j

отрабатывает одинаково правильно на обоих осях.



Изначально меня сбило с толку то, что если вынести значения в переменную за пределы цикла, переменная обретает верное значение, в противоречие тому, что внутри цикла "не работает" оператор NEQ. Причём оператор EQU, как я уже говорил, работал. На примере приведённого мной (неверного) кода:

Код:

Код: Выделить всё

@echo Off
Cls
Setlocal enableextensions
For /F "Tokens=2*" %%I In ('2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /V InstallLocation') Do set LocationI=%%I
if defined LocationI echo I: "%LocationI%"
For /F "Tokens=2*" %%I In ('2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /V InstallLocation') Do set LocationJ=%%J\
if defined LocationJ echo J: "%LocationJ%"
For /F "Tokens=2*" %%I In ('2^>nul Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /V InstallLocation') Do if /I "%%J\" NEQ "%~dp0" Goto label
Echo 0: "%~dp0"
Echo Каталоги совпадают
Pause
Exit
:label
Echo 0: "%~dp0"
Echo Каталоги НЕ совпадают
Pause
Exit
REM Результат на WinXP:
REM I: "REG_SZ"
REM J: "C:\Program Files\CCleaner\"
REM 0: "C:\Program Files\CCleaner\"
REM Каталоги НЕ совпадают
REM Для продолжения нажмите любую клавишу . . .
REM Результат на Win7:
REM I: "REG_SZ"
REM J: "C:\Program Files\CCleaner\"
REM 0: "C:\Program Files\CCleaner\"
REM Каталоги совпадают
REM Для продолжения нажмите любую клавишу . . .

В дополнение, команда:

Код:

Код: Выделить всё

Reg Query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner" /V InstallLocation

на WinXP и на Win7 выдаёт 4 строки :

Код:

Код: Выделить всё

REM WinXP:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner
    InstallLocation     REG_SZ  C:\Program Files\CCleaner
REM Win7:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CCleaner
    InstallLocation    REG_SZ    C:\Program Files\CCleaner

Но есть разница: на XP между строк "REG_SZ" и "C:\Program Files\CCleaner" - 2 пробела, а на Семёрке - 4.



Georgio спасибо за детальное объяснение, буду разбираться...
Аватара пользователя
Lucretius

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Lucretius »

Цитата Lucretius:



По поводу знака табуляции - подтверждаю, работает на XP, но не работает на семёрке
CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"




Потому я и предпочитаю WSH/PoSH — у них нет такой зависимости от версий внешних утилит.




Цитата Lucretius:



на XP между строк "REG_SZ" и "C:\Program Files\CCleaner" - 2 пробела,
CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"




Перенаправьте вывод в файл: там табуляция, а не пробелы. А уж количество пробелов подбирает редактор или вьюер.
Аватара пользователя
Iska

Re: CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Сообщение Iska »

Iska, верно, перенаправил в файл, открыл в hex - табуляция...
Ответить

Вернуться в «Скриптовые языки администрирования Windows»