Вложенный DOS для проблем с циклом - PullRequest
1 голос
/ 18 сентября 2011

Моя цель с помощью этого пакетного файла - быстро узнать, сколько антивирусных приложений установлено пользователем. Я планирую сделать это, используя два цикла for:

  • Внешний цикл: перебирать имена папок в каталоге Program Files
  • Внутренний цикл: перебирайте список распространенных имен антивируса (переменная AVList), ищите совпадения с текущим именем каталога и добавляйте каждое совпадение к переменной AntiVirus.

С учетом сказанного, вот мой ошибочный код. Ошибка, которую я получаю, "", была неожиданной в это время. . Обратите внимание, что в настоящее время у меня есть имена папок в моих программных файлах в переменной AVList (для целей тестирования).

::@echo off
::variables
set AntiVirus="Initial Value"
set AVList=(adobe ccleaner auslogics)

SETLOCAL EnableDelayedExpansion

echo Checking Program Files...

if "%Processor_Architecture%" == "AMD64" (
echo 64-bit OS
echo.
for /d %%f in ("%ProgramFiles(x86)%\*") do (
   echo "%%f"
   SET "folder=%%f"
   REM Begin loop to search substrings with words in AVList
   Call:SearchAV "%folder%"
   )
) 
else echo 32-bit OS

echo.
echo AntiVirus: %AntiVirus%
echo.

for /d %%g in ("%ProgramFiles%\*") do (
   echo "%%g"
   SET "folder=%%g"
   REM Begin loop to search substrings with words in AVList
   Call:SearchAV "%folder%"
   )
)

:SearchAV
for %%v in ("%AVList%") do (
  echo "%%v"
  SET "av=%%v"
  if /I NOT "!~1:av=!"=="!~1!" set AntiVirus="%AntiVirus%%av%"
 )
GOTO:EOF

echo.
echo.
echo %AntiVirus% found
echo.
echo Script created by Matthew Ammann, revised by Andriy M from StackOverflow

@pause

Вот вывод, перенаправленный в файл журнала:

C:\AVFinder>set AntiVirus="Initial Value" 

C:\AVFinder>set AVList=(adobe ccleaner auslogics) 

C:\AVFinder>SETLOCAL EnableDelayedExpansion 

C:\AVFinder>echo Checking Program Files... 
Checking Program Files...

C:\AVFinder>if "AMD64" == "AMD64" (
echo 64-bit OS  
 echo. 
 for / %f in ("C:\Program Files (x86)\*") do (
echo "%f"  
 SET "folder=%f"  
 REM Begin loop to search substrings with words in AVList  
 Call:SearchAV "C:\Program Files (x86)\Adobe" 
) 
) 
64-bit OS


C:\AVFinder>(
echo "C:\Program Files (x86)\Adobe"  
 SET "folder=C:\Program Files (x86)\Adobe"  
 REM Begin loop to search substrings with words in AVList  
 Call:SearchAV "C:\Program Files (x86)\Adobe" 
) 
"C:\Program Files (x86)\Adobe"
"" was unexpected at this time.

C:\AVFinder>  if /I NOT "!~1:av=!"=="!~1!" set AntiVirus=""Initial Value""(adobe ccleaner auslogics)""

Где я иду не так?

ОБНОВЛЕНИЕ: Я наконец нашел время, чтобы это исправить. Вот обновленный код:

::This script is licensed under the Creative Commons Attribution license (CC BY 3.0) 
::Simply mention the original author in the source code if you make a derivative work.

@echo off
::variables
set AntiVirus=
set AVList=(norton mcafee kaspersky symantec avg comodo avast avira webroot eTRUST)

SETLOCAL EnableDelayedExpansion

echo Checking Program Files...

if "%Processor_Architecture%" == "AMD64" (
echo 64-bit OS
echo.
for /d %%f in ("%ProgramFiles(x86)%\*") do (
   echo "%%f"
   SET "path=%%f"
   Call:SearchAV "!path!"
   )
) else echo 32-bit OS

for /d %%g in ("%ProgramFiles%\*") do (
   echo "%%g"
   SET "path=%%g"
   Call:SearchAV "!path!"
   )
)
goto :END

:SearchAV
FOR %%a in %AVLIST% do (
  set res="%~n1"
  set res=!res:%%a=!
  if NOT "%~n1" ==!res! (
        ECHO "%~n1"  contains %%a
        if [!AntiVirus!] == [] (
            set AntiVirus="%~n1"
        ) else (
            set AntiVirus=!AntiVirus!, "%~n1"
        )   
    )
)
goto :eof

:END
echo.
echo.
echo !AntiVirus! found
echo.
echo Script created by Matthew Ammann, revised by members of Stack Overflow
echo 

@pause

Ответы [ 2 ]

5 голосов
/ 18 сентября 2011

Я вижу несколько проблем

1.-Место, где у вас есть подпрограмма :searchAV, не позволяет выполнить окончательный код.Итак, переместите процедуру в конец файла BAT;и замените PAUSE на GOTO :EOF.См. HELP CALL

2.- Для установки переменной среды в цикле необходимо задержанное расширение для правильного назначения.А для отложенного расширения требуется обозначение !VAR! для проверки.Итак, измените %FOLDER% на !FOLDER!.Но вам это все равно не нужно, так как вы можете напрямую использовать переменную цикла, %%g в вашем случае.Смотри HELP SET.

3.- Зацикливание всех элементов в списке строк не работает с командой FOR с использованным вами синтаксисом.См. HELP FOR.

Итак, взгляните на этот отрывок, чтобы узнать, как исправить файл BAT ...

@ECHO off
SETLOCAL enabledelayedexpansion
set AVLIST=(Windows Microsoft)
FOR /d %%a in ("%ProgramFiles%\*") do (
   CALL :searchAV "%%a"
   )
GOTO :eof

:searchAV
FOR %%a in %AVLIST% do (
  set res=%1
  set res=!res:%%a=!
  if NOT %1==!res! ECHO %1 contains %%a
 )
GOTO :eof
2 голосов
/ 18 сентября 2011

Ошибка "" was unexpected at this time. исходит из окружающих кавычек в set AntiVirus="%AntiVirus%%av%" в вашей подпрограмме SearchAV.%av% установлено на "%AVList%", то есть: "(adobe ccleaner auslogics)", и поскольку %AntiVirus% пусто в начале, вы пытаетесь установить AntiVirus на ""(adobe ccleaner auslogics)"".SET здесь, похоже, не нравятся пустые кавычки, отсюда и проблема.

Помимо этого, вы также можете рассмотреть следующие моменты:

  • else echo 32-bit OS необходимонаходиться на той же строке, что и соответствующие ей if.
  • первый и второй for циклы: %folder% необходимо изменить на !folder!, чтобы извлечь выгоду из замедленного расширения переменной.
  • Подпрограмма :SearchAV: цикл for не зацикливает имена антивирусов (%%v остается равным "(adobe ccleaner auslogics)", !~1:av=! всегда равно av= и !~1! остается пустым).Вместо этого я бы использовал for /f для токенизации списка.
  • необходимо добавить goto после окончания второго цикла for, чтобы вы больше не проходили подпрограмму.

Вот моя попытка:

@echo off
set AntiVirus=
set AVList=Norton AntiVirus:ccleaner:auslogics

SETLOCAL EnableDelayedExpansion

echo Checking Program Files...

if "%Processor_Architecture%" == "AMD64" (
echo 64-bit OS
echo.
  for /d %%f in ("%ProgramFiles(x86)%\*") do (
    echo %%f
    SET folder=%%f
    REM Begin loop to search substrings with words in AVList
    call :SearchAV "!folder!"
  )
) else echo 32-bit OS

echo.
echo AntiVirus (x86): %AntiVirus%
echo.

set AntiVirus=
for /d %%g in ("%ProgramFiles%\*") do (
   echo %%g
   SET folder=%%g
   REM Begin loop to search substrings with words in AVList
   Call:SearchAV "!folder!"
   )
)

echo.
echo AntiVirus: %AntiVirus%
goto :end

:SearchAV
set list=%AVList%
:tokenize
for /f "tokens=1* delims=:" %%v in ("!list!") do (
  SET av=%%v
  SET list=%%w
  if /I "!av!" == "%~n1" ( 
    if [!AntiVirus!] == [] (
        set AntiVirus=!av!
    ) else (
        set AntiVirus=!AntiVirus!, !av!
    )
  )
)
if not [!list!] == [] goto :tokenize
goto :eof

:end

Надеюсь, это поможет.

...