Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

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

Пользователь


Сообщения: 65
Благодарности: 7

Профиль | Отправить PM | Цитировать


Изменения
Автор: Lucretius
Дата: 23-05-2013
Описание: Опечатка
Включил в батник следующие строки:
Код: Выделить весь код
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 ОБА варианта работают правильно.

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

Отправлено: 18:09, 22-05-2013

 

Пользователь


Сообщения: 65
Благодарности: 7

Профиль | Отправить PM | Цитировать


Если включить в скрипт конструкции:
Код: Выделить весь код
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, 22-05-2013 в 18:48.


Отправлено: 18:33, 22-05-2013 | #2



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

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


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


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 могут отдавать разную информацию, проверяйте.
Это сообщение посчитали полезным следующие участники:

Отправлено: 23:24, 22-05-2013 | #3


Ветеран


Сообщения: 874
Благодарности: 575

Профиль | Отправить PM | Цитировать


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

Вся проблема заключена в результате выполнения команды
Код: Выделить весь код
REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*******" /V InstallLocation

Не знаю, как в других версиях утилиты reg.exe, но у меня как в 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 не обрабатываются. Отсюда следует, что команда 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*" команда 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 уже определяется во второй (первой из непустых) строке и принимает значение 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" -- это и есть пропуск двух первых строк при обработки командой FOR (в этом ключе в расчёт обязательно берутся и пустые строки).

Последний раз редактировалось Georgio, 23-05-2013 в 07:48. Причина: изменение тегов

Это сообщение посчитали полезным следующие участники:

Отправлено: 06:32, 23-05-2013 | #4


Ветеран


Сообщения: 874
Благодарности: 575

Профиль | Отправить PM | Цитировать


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
И откуда-то в коде взялась табуляция...

Отправлено: 06:53, 23-05-2013 | #5


Ветеран


Сообщения: 874
Благодарности: 575

Профиль | Отправить PM | Цитировать


Вот, уж (в данном значении "уж" -- не пресмыкающееся), что работает некорректно, так это переведённая справка командной строки по операторам сравнения (Windows 7 Starter). Для тех, кто хочет улыбнуться (не "оффтоп") --
читать дальше »
Решил посмотреть по данной теме справку, -- вдруг что-нибудь новое. Набираю: "if/?", прокручиваю, ничего интересного не нахожу, прокручиваю в обратном направлении и... стоп... нашёл нечто новое.

Привожу "копипаст" из командной строки (новость выделена красным цветом):

Цитата:
Изменение команды IF при включении расширенной обработки команд:

IF [/i] строка1 оператор_сравнения строка2 команда
IF CMDEXTVERSION число команда
IF DEFINED переменная команда

где оператор_сравнения принимает следующие значения:

EQL - равно
NEQ - не равно
LSS - меньше
LEQ - меньше или равно
GTR - больше
GEQ - больше или равно,
<...>
Да-да, именно так -- EQL. Подумал, наверное, соринка к монитору прилипла и не даёт увидеть полностью букву U. Прокрутил, -- без изменений: EQL. Уже, было, решил, -- наверное, оператор EQU "совместным постановлением партии и правительства" было решено переименовать в EQL. Что ж делать, в жизни всё случается. И ,не подумайте плохого, проверил:

Цитата:
C:\Users\1>IF ABC EQL ABC ECHO ABC
Непредвиденное появление: EQL.
Фух, на сей раз пронесло. И жизнь прекрасна и удивительна.

Отправлено: 09:11, 23-05-2013 | #6


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата Georgio:
И откуда-то в коде взялась табуляция... »
Она там и была. И именно табуляция. И именно потому команда «for /f» осуществляет разбор правильно, и под Windows XP в:
Цитата Georgio:
Iska, Ваш скрипт работает правильно только в случаях, когда в значении параметра InstallLocation отсутствуют пробелы. Поэтому надо так: »
не было необходимости:

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

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

Я потому и писал:
Цитата Iska:
Версии «reg.exe» под Windows XP и Windows 7 могут отдавать разную информацию, проверяйте. »
Цитата Georgio:
так это переведённая справка командной строки по операторам сравнения (Windows 7 Starter) »
И в Windows 7 всё та же песня? Так и тянется четырнадцать лет?!
Это сообщение посчитали полезным следующие участники:

Отправлено: 15:54, 23-05-2013 | #7


Пользователь


Сообщения: 65
Благодарности: 7

Профиль | Отправить PM | Цитировать


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

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, но не работает на семёрке я поднимал уже эту тему здесь.

Кстати, с пробелом в качестве разделителя:
Код: Выделить весь код
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, 23-05-2013 в 22:17.


Отправлено: 21:39, 23-05-2013 | #8


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата Lucretius:
По поводу знака табуляции - подтверждаю, работает на XP, но не работает на семёрке »
Потому я и предпочитаю WSH/PoSH — у них нет такой зависимости от версий внешних утилит.


Цитата Lucretius:
на XP между строк "REG_SZ" и "C:\Program Files\CCleaner" - 2 пробела, »
Перенаправьте вывод в файл: там табуляция, а не пробелы. А уж количество пробелов подбирает редактор или вьюер.

Отправлено: 22:35, 23-05-2013 | #9


Пользователь


Сообщения: 65
Благодарности: 7

Профиль | Отправить PM | Цитировать


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

Отправлено: 22:53, 23-05-2013 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - [решено] Некорректная работа оператора сравнения "neq"

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Ошибка просмотра фото - "прекращена работа программы "COM SURROGATE" illusionmgs Хочу все знать 4 18-03-2014 19:20
Всплывает сообщение "Прекращена работа программы "Hosts file cleaner" AlexPSPb Лечение систем от вредоносных программ 4 08-01-2012 14:33
Интерфейс - [решено] Как удалить папку "Моя музыка","Мои Картинки", "Мое видео"? verdix Microsoft Windows 2000/XP 3 03-10-2009 23:46
Запретить/удалить пункт "Programs" ("Программы") из меню кнопки "Start" ("Пуск") submaster Microsoft Windows NT/2000/2003 5 13-09-2006 12:29




 
Переход