Search code examples
windowsbatch-filecmdscopeexpansion

Variable not recognized in else statement in a bat file


I have the follow code:

ECHO OFF
:LOOP
set c=
setlocal ENABLEDELAYEDEXPANSION
tasklist | find /i "calc.exe" >nul 2>&1
IF %ERRORLEVEL% == 0 (
  ECHO easymeetingOnCall is running
  taskkill /IM calc.exe /F
  set c=true
  Timeout /T 10
  goto LOOP
) ELSE (
  IF "!c!" == "true" (
    ECHO l'applicazione easymeetingOnCall è spenta.
    Timeout /T 10
    goto exitLoop
  )
  ECHO easymeetingOnCall is not running
  Timeout /T 5 /Nobreak
  GOTO LOOP
)
:exitLoop

My problem is that the follow condition

IF "!c!" == "true"

Into the else statement, is not recognized. If I write echo !c! It doesn't output any result. I set enabledelayedexpansion before, so I don't know why of this behavior.

Could you help me? Thanks to all.


Solution

  • Look carefully at the following extraction from your code.

    ECHO OFF
    :LOOP
    set c=
    ....
    set c=true
    goto :LOOP
    

    You are explicitly telling the if statement to goto :loop where directly after you set c= which now gives it no value. Move the set c= to above to label to retain the value you've set.

    I however suggest a few changes. you can get away without delayedexpansion and do actually require all the for loops. Using taskkill to explicitly search for the app is better than listing all, also already mentioned to you in a comment by @Mofi. Lastly, it is not really good practice to set single character variables, though it does not always cause issues, I would suggest using multple character variable names. I just changed your variable %c% to %_c%

    @echo off & set _c=
    :loop
    tasklist /FI "IMAGENAME eq Calc.exe" | find /i "Calc"
    goto :_%errorlevel%
    :_0
      ECHO easymeetingOnCall is running
      taskkill /IM calc.exe /F
      set _c=true
      Timeout /T 10
      goto loop
    :_1
      IF "%_c%" == "true" (
        ECHO l'applicazione easymeetingOnCall è spenta.
        Timeout /T 10
        goto exitloop
      )
      ECHO easymeetingOnCall is not running
      Timeout /T 5 /Nobreak
      goto loop
      :exitloop
    

    Edit, as you wanted to do this with a list:

    @echo off & set _c=
    set "list=calc.exe StickyNot.exe wordpad.exe"
    for %%a in (%list%) do call :loop %%a
    goto :eof
    :loop
    set task=%1
     tasklist /FI "IMAGENAME eq %1" | find /i "%1"
       if not errorlevel 1 (
       ECHO easymeetingOnCall is running %1
       taskkill /IM %1 /F
       set _c=true
       Timeout /T 10
    )
    if "%_c%" == "true" (
        ECHO l'applicazione easymeetingOnCall è spenta. %1
        Timeout /T 10
        goto exitloop
      )
        echo easymeetingOnCall is not running %1
        Timeout /T 5 /Nobreak
        goto :loop
      :exitloop
    

    Be aware, if the first process is not running, it will loop forever until it is found, then only kill it and go to the next process. If you do not want that, then change goto :loop in the last line to exit loop.