IF condition is completly ignored, but why?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
NoNameFound
Posts: 2
Joined: 06 Jun 2011 08:55

IF condition is completly ignored, but why?

#1 Post by NoNameFound » 06 Jun 2011 09:02

Hi there :-)

I've been trying to write a small programm that checks if one or more services are running and if so, terminates these services. Apart from trying it on my own, I also looked up some examples in google and finally came up with the following mixture of own code and found code:

Code: Select all

setlocal
@echo off 
cls

rem ====================================================================== 
:: 
::  Service Searcher And Terminator 
:: 
rem ---------------------------------------------------------------------- 
::  2011-06-06  v1.0  NoNameFound 
rem ======================================================================

rem ---------------------------------------------------------------------- 
::  CONFIG 
rem ---------------------------------------------------------------------- 
   set lServices= 
   set lServices=%lServices% "Spooler"
    
   set tmpfile=%temp%\services_.tmp
     
     
rem ---------------------------------------------------------------------- 
:: MAIN 
rem ---------------------------------------------------------------------- 
   color 08 
   echo. 
   echo ===== SERVICE SEARCH AND DESTROY ===== 
   echo. 
   call :getStatus 
   echo Stopped - %Stopped% ..  Running - %Running% 
        if "%Stopped%" == "N" call :stopServices
   echo. 
   color cf 
   echo. 
   echo --- INFO --- 
   echo Service is not running. 
   echo. 
   goto end 

rem ---------------------------------------------------------------------- 
::  SUBS 
rem ---------------------------------------------------------------------- 
   :getStatus 
   set Stopped=N 
   set Running=N 
   echo.
   echo Reading service state ... 
   net start >"%tmpfile%" 
   for %%a in (%lServices%) do call :checkService %%a 
   del "%tmpfile%" 
   echo. 
   goto end2   

   :checkService 
   echo.
   findstr /c:%1 "%tmpfile%" >nul && ( echo YES: %1 is running && set Running=Y && goto end2) 
   echo NO: %1 is stopped && set Stopped=Y 
   goto end2

   :stopServices 
   color 17 
   echo --- Stopping service --- 
   pause 
   for %%a in (%lServices%) do ( 
      echo ... stopping %%a ...
      echo.
      net stop %%a 
   ) 
   call :getStatus 
   goto end 


rem ---------------------------------------------------------------------- 
::  END 
rem ---------------------------------------------------------------------- 

   :end   
   echo --- done ---
   endlocal
   pause 

   :end2 

rem ---------------------------------------------------------------------- 
::  EOF 
rem ---------------------------------------------------------------------- 


The first if condition under :Main "if "%Stopped%" == "N" call :stopServices" is completly ignored, although the variable is infact set to "N".

Can someone shed some light on why this is the case?

Cheers and thanks,

Fred

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: IF condition is completly ignored, but why?

#2 Post by Ed Dyreen » 06 Jun 2011 10:08


Right right, so you want to do something like this right ?

Code: Select all

@echo off &setLocal EnableDelayedExpansion

set "AntiVirus.STATE=Disabled"
::
for /f "skip=1 tokens=*" %%! in (

   'net start'

) do (
   set "STATE=%%~!"
   ::
   set "STATE=!STATE:~0,8!"
   ::
   for %%! in (

      "Symantec"

   ) do    if /i ["!STATE!"] == ["%%~!"] (
      ::
      set "AntiVirus.STATE=Enabled"
   )
)

if /i ["!AntiVirus.NAME!"] == ["Norton Internet Security"] if /i ["!AntiVirus.STATE!"] neq ["Disabled"] (
   ::
   echo.
   for %%! in (

      "Symantec AppCore Service"
      "Symantec Core LC"
      "Symantec Event Manager"
      "Symantec Lic NetConnect service"
      "Symantec Settings Manager"
      "System Event Notification"

   ) do    net start |>nul findstr.EXE /i /c:"%%~!" &&(
      ::
      echo. Sending '%%~!' the KILL signal...
      ::
      net stop "%%~!" /y ||(
         ::
         set /a ERR = !ErrorLevel!

         set /p "?= [ERROR:!ERR!]" <nul &echo.
      )
   )
)
pause
exit /b

That is a nogo ! Change this first :
"if "%Stopped%" == "N"

if /i ["%Stopped%"] == ["N"]

Change this too:
set lServices=%lServices% "Spooler"
set tmpfile=%temp%\services_.tmp

set "lServices=%lServices% "Spooler""
set "tmpfile=%temp%\services_.tmp"

Try to always use set like this: set "var=something"
and if like: if /i ["some"] == ["some"]

A a aaa! NO goto like that
goto end

goto :end

You've got a lot to learn my friend, that's ok, we'll teach you :wink:
Last edited by Ed Dyreen on 06 Jun 2011 10:16, edited 1 time in total.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: IF condition is completly ignored, but why?

#3 Post by dbenham » 06 Jun 2011 10:16

NoNameFound wrote:The first if condition under :Main "if "%Stopped%" == "N" call :stopServices" is completly ignored, although the variable is infact set to "N".
No it isn't. You have spaces after the N in your assignmet :!:

You can avoid this problem by using quotes around the entire assignment like so:
set "Running=N"

Extra spaces after the closing quote will be ignored.

Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: IF condition is completly ignored, but why?

#4 Post by Ed Dyreen » 06 Jun 2011 10:17

'
Take this through will you ? You'll then be able to solve this problem with your eyes closed.
MS-DOS/MSDOS Batch Files: Batch File Tutorial and Reference :arrow:
http://www.allenware.com/icsw/icswidx.htm

orange_batch
Expert
Posts: 442
Joined: 01 Aug 2010 17:13
Location: Canadian Pacific
Contact:

Re: IF condition is completly ignored, but why?

#5 Post by orange_batch » 06 Jun 2011 12:59

Jeez Ed :?

You know, the brackets [ ] in these situations are useless:

if /i ["some"]==["some"]

The brackets themselves are just a character choice, it could be any other character. They don't even need to be on both sides of each condition. As for the technique, it's only useful for optional argument checking where quotations are optional so as to prevent either a blank argument error or undoing the quotation deactivation of command characters within the argument.

NoNameFound
Posts: 2
Joined: 06 Jun 2011 08:55

Re: IF condition is completly ignored, but why?

#6 Post by NoNameFound » 07 Jun 2011 01:25

Hey guys,

thanks for the really quick answers! I'm impressed :-) I'll read the linked infos right away - thanks for that aswell :-)

I'll change my script and post the results then - in any case thank you very much :-)

Cheers,

Fred

EDIT:

*YaY* it worked! The tip with the empty spaces did the trick, although I also used all other tips to clean up the script. The result is this:

Code: Select all


setlocal
@echo off 
cls

rem ====================================================================== 
:: 
::  Service Searcher And Terminator 
:: 
rem ---------------------------------------------------------------------- 
::  2011-06-06  v1.1  NoNameFound 
rem ======================================================================

rem ---------------------------------------------------------------------- 
::  CONFIG 
rem ---------------------------------------------------------------------- 
   set "lServices=" 
   set "lServices=%lServices% "Druckwarteschlange""
    
   set "tmpfile=%temp%\services_.tmp" 

   set "MaxCount=5"
   set "Count=0"
     
     
rem ---------------------------------------------------------------------- 
:: MAIN 
rem ---------------------------------------------------------------------- 
   color 08 
   echo. 
   echo ===== SERVICE SEARCH AND DESTROY ===== 
   echo. 
   call :getStatus 
   echo Stopped - %Stopped% ..  Running - %Running% 
      if /i ["%Stopped%"]==["N"] call :stopServices
   echo. 
   color cf 
   echo. 
   echo --- INFO --- 
   echo Service is not running. 
   echo. 
   goto :end 

rem ---------------------------------------------------------------------- 
::  SUBS 
rem ---------------------------------------------------------------------- 
   :getStatus 
   set "Stopped=N" 
   set "Running=N" 
   echo.
   echo Reading service state ... 
   net start >"%tmpfile%" 
   for %%a in (%lServices%) do call :checkService %%a 
   del "%tmpfile%" 
   echo. 
   goto :end2   

   :checkService 
   echo.
   findstr /c:%1 "%tmpfile%" >nul && ( echo YES: %1 is running && set "Running=Y" && goto :end2) 
   echo NO: %1 is stopped && set "Stopped=Y" 
   goto :end2

   :stopServices 
   color 17 
   echo --- Stopping service --- 
   pause 
   for %%a in (%lServices%) do ( 
      echo ... stopping %%a ...
      echo.
      net stop %%a 
   ) 
   call :getStatus 
   goto :end 


rem ---------------------------------------------------------------------- 
::  END 
rem ---------------------------------------------------------------------- 

   :end   
   echo --- done ---
   endlocal
   pause 

   :end2 

rem ---------------------------------------------------------------------- 
::  EOF 
rem ---------------------------------------------------------------------- 



Next step: add logging to the script, but that's easy :-)

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: IF condition is completly ignored, but why?

#7 Post by Ed Dyreen » 07 Jun 2011 04:29


Ok, I can't explain this. Maybe Jeb can explain it.
You know, the brackets [ ] in these situations are useless:

But I have seen this fail
if "" == ""
I've not seen this fail yet
if [""] == [""]

And I don't even know if it's WinXP that needs if [""] == [""] :|

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: IF condition is completly ignored, but why?

#8 Post by dbenham » 07 Jun 2011 06:03

EdDyreen wrote:But I have seen this fail
if "" == ""
I've not seen this fail yet
if [""] == [""]
I think you may have fooled yourself. If 1st method fails, then 2nd will fail as well. IF statements typically fail because of unquoted, un-escaped special characters, or because of undefined variables. Simple logic should tell us what works and what doesn't.

This fails because quoted & in variable becomes unquoted in IF:

Code: Select all

set str="A&B"
if "%str%"=="" (echo empty) else echo not empty
As does this:

Code: Select all

set str="A&B"
if ["%str%"]==[""] (echo empty) else echo not empty


This succeeds because quoted & in variable remains quoted in IF:

Code: Select all

set str="A&B"
if [%str%]==[] (echo empty) else echo not empty
But this fails because unquoted & in variable remains unquoted in IF:

Code: Select all

set "str=A&B"
if [%str%]==[] (echo empty) else echo not empty


This fails because quoted & in variable becomes unquoted in IF:

Code: Select all

set str="A&B"
if "%str%"=="" (echo empty) else echo not empty
But this succeeds because unquoted & in variable becomes quoted in IF:

Code: Select all

set "str=A&B"
if "%str%"=="" (echo empty) else echo not empty


When variable contains both quoted and unquoted special character - we really have problems. Note that in these examples the unquoted & is not escaped within the variable.
This fails at the 2nd &:

Code: Select all

set str=A^&"B&C"
if "%str%"=="" (echo empty) else echo not empty
This fails at the 1st &:

Code: Select all

set str=A^&"B&C"
if [%str%]==[] (echo empty) else echo not empty


The only way I know to guarantee an IF statement will work is to use delayed expansion (or else escape special characters as needed via a preprocess - too complicated)
These all succeed:

Code: Select all

setlocal enableDelayedExpansion
set str1="A&B"
set "str2=A&B"
set str3=A^&"B&C"
set "str4="
if "!str1!"=="" (echo empty) else echo not empty
if "!str2!"=="" (echo empty) else echo not empty
if "!str3!"=="" (echo empty) else echo not empty
if "!str4!"=="" (echo empty) else echo not empty
if [!str1!]==[] (echo empty) else echo not empty
if [!str2!]==[] (echo empty) else echo not empty
if [!str3!]==[] (echo empty) else echo not empty
if [!str4!]==[] (echo empty) else echo not empty
if x!str1!==x (echo empty) else echo not empty
if x!str2!==x (echo empty) else echo not empty
if x!str3!==x (echo empty) else echo not empty
if x!str4!==x (echo empty) else echo not empty


You need something added in case the string is empty. This fails:The statement in red is FALSE. The code below works as would be expected! Thanks jeb for pointing out the error of my ways.

Code: Select all

setlocal enableDelayedExpansion
set "str="
if !str!==test (echo match) else echo no match

In summary:
With delayed expansion DISABLED, quotes guard against empty string but fail with quoted special characters.
With delayed expansion DISABLED, non quotes guard against empty string but fail with unquoted special characters.
With delayed expansion ENABLED, empty strings and special characters are not a concern.

Note however that delayed expansion with substring or search and replace expression does not work if the variable is undefined. (for example !str:~1,3! and !str:a=b! both give undesired result if str is undefined).

Dave Benham
Last edited by dbenham on 07 Jun 2011 13:58, edited 2 times in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: IF condition is completly ignored, but why?

#9 Post by Ed Dyreen » 07 Jun 2011 06:10

And I don't even know if it's WinXP that needs if [""] == [""] :|

@dbenham Did you also try this in WinME :?:

I need WinME's Command.COM for my NetBootDisk installation of XP.
http://www.netbootdisk.com/download.htm

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: IF condition is completly ignored, but why?

#10 Post by dbenham » 07 Jun 2011 08:05

Everything in my last post should remain true for command.com, up until the delayed expansion part. Command.com does not support command extensions so delayed expansion is not available.

Dave

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: IF condition is completly ignored, but why?

#11 Post by Ed Dyreen » 07 Jun 2011 08:41

Maybe you are right, dunno, but I still gona fool myself for awile then ey :twisted:

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: IF condition is completly ignored, but why?

#12 Post by jeb » 07 Jun 2011 13:02

dbenham wrote:You need something added in case the string is empty. This fails:
Code:
setlocal enableDelayedExpansion
set "str="
if !str!==test (echo match) else echo no match


I got you :!: you didn't test it.

It works as expected even with an empty string.

This is an effect of the IF parser, the parser split the line at then "==" and when the !str! is expanded it isn't longer important if it is empty.

But as the parser isn't very smart, it fails with something like

Code: Select all

if !str:the=it!==test_it  (echo match) else echo no match

jeb

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: IF condition is completly ignored, but why?

#13 Post by dbenham » 07 Jun 2011 13:37

jeb wrote:I got you :!: you didn't test it.

Yes you did :!: :oops:

I could have sworn I had tested that before, though obviously not that specific bit of code. This certainly demonstrates the danger of posting code based on memory, and without testing. My bad.

Are you aware of a situation where the delayed expansion of a variable needs quotes :?: I thought I had run accross this, but now I'm not so sure.

Dave

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: IF condition is completly ignored, but why?

#14 Post by jeb » 07 Jun 2011 15:46

dbenham wrote:Are you aware of a situation where the delayed expansion of a variable needs quotes :?: I thought I had run accross this, but now I'm not so sure.
No, I believe that there isn't any situation you need quotes for a delayed expansion.
But there are situations, where the delayed expansion fails, always.

Code: Select all

setlocal EnableDelayedExpansion
set "myDelims=ab"
for /F "tokens=1,2,3 delims=!myDelims!" %%x in ("**a**b**m**???") do echo x="%%x" y="%%y"

set "conditionA=1 EQU 1"
if !conditionA! (echo condition is true)

The delims are set to "!eDilms" not to "ab"
The condition fails completly.

Both failures seems to be an effect of the specialized parser of FOR and IF,
as both parsers splits the line into different parts, and some parts supports delayed expansion, but not all.

jeb

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: IF condition is completly ignored, but why?

#15 Post by dbenham » 07 Jun 2011 23:04

jeb wrote:Both failures seems to be an effect of the specialized parser of FOR and IF,
as both parsers splits the line into different parts, and some parts supports delayed expansion, but not all.
Yes, I ran into a variation of that recently. The following fails:

Code: Select all

setlocal enableDelayedExpansion
set option=/I
if !option! a==A echo OK


jeb wrote:No, I believe that there isn't any situation you need quotes for a delayed expansion.

I found a case that requires quotes :!: (vindication ? :lol: )

Code: Select all

setlocal enableDelayedExpansion
cmd /c exit 0

rem this succeeds
if "!=exitCode!"=="00000000" echo OK

rem this fails!
if !=exitCode!==00000000 echo OK
The problem exists for all of the = variables. The only way I have gotten any of them to work is with quotes. No other character(s) seem to work. Very odd :?

Dave Benham

Post Reply