0

I want to set VAR2 and other variables if VAR is already defined, on the basis of below code:

@ECHO ON
SET ABC=IQ
SET VAR=value
ECHO %VAR%
VERIFY OTHER 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (
    ECHO Unable to enable extensions
)
IF DEFINED VAR (
    IF "%VAR%" == "code" call :Result
    IF "%VAR%" == "code2" call :Result
    IF "%VAR%" == "value" call :Result
    SET VAR2=C:\abc\files
) ELSE (
    SET VAR2=C:\abc\file\pic & ECHO VAR not defined
)
endlocal & SET VAR3=val
:Result
      SET NAME=CODE & SET VAR2=C:\abc\file

When i execute above code i get output:

SET ABC=IQ
SET VAR=valu
ECHO valu
valu
VERIFY OTHER 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (ECHO Unable to enable extensions )
IF DEFINED VAR (
IF "valu" == "code" call :Result
 IF "valu" == "code2" call :Result
 IF "valu" == "value" call :Result
 SET VAR2=C:\abc\files
) ELSE (SET VAR2=C:\abc\file\pic & ECHO VAR not defined )
endlocal & SET VAR3=val
SET NAME=CODE & SET VAR2=C:\abc\file

BUT when VAR is not defined, even than :RESULT section is getting executed. And Also when VAR != value, even than :RESULT section is getting executed. Any suggestions why it`s so??

POOJA SINGH
  • 43
  • 11
  • 1
    The code above will always set `VAR2` to a (not empty) value. Please post the *real* code, including the parts where you set `VAR` and echo `VAR2`. Note that if you look at `VAR2` outside the batch file any values you set inside it are lost because of `setlocal`. – dxiv Apr 30 '20 at 21:18
  • 3
    [Something to read regarding the reason Not to target labels inside code Blocks as you have done here](https://stackoverflow.com/a/8481978/12343998) If not for the erroneous use of Goto, the result of those conditions would be the execution of the else statement (given Var is not being shown as Defined in the example) – T3RR0R Apr 30 '20 at 22:39
  • Yes, `goto :Label` cannot be used within a parenthesised block of code; but even if it worked, the code as it stands it is just useless, because independent on what `VAR` carries, execution would always continue at `:Result`... – aschipfl Apr 30 '20 at 22:58
  • 1
    When a batch file ends, there is an implicit `endlocal` (when there was a `setlocal` in the batchfile), so you loose all your variables set or changed after `setlocal` at that point. – Stephan May 01 '20 at 21:16
  • After your code update: The observed result is totally legit... your code does set VAR to "value" does some more lines and goes to End in the last line of your :Result block... if you do an `echo %VAR%` on the command line after that, a "value" output is printed as should be expected. Or which value should %VAR% have in your opinion? – Antares May 02 '20 at 00:42
  • @Stephan But I wanted to use DEFINED, and when I googled SETLOCAL ENABLEEXTENSIONS part of code was required for checking whether DEFINED is working or not(According to this link: https://www.robvanderwoude.com/battech_defined.php). Now when I removed that part my code is working fine. But will it generate any future issues if I run this code on the server? – POOJA SINGH May 03 '20 at 19:13
  • @dxiv But setlocal part is required if I use DEFINED according to this link: https://www.robvanderwoude.com/battech_defined.php – POOJA SINGH May 03 '20 at 19:22
  • 1
    @POOJASINGH If you want to keep `setlocal` but pass variables back to the caller (in your case, the cmd prompt), you'll need to add a line `exit /b & set "var=%var%" & set "var2=%var2%" & set "var3=%var3%"` at the very end of your batch file. – dxiv May 03 '20 at 19:51
  • @dxiv I want the form, which I have written in the updated code above. Since I want to set values on the basis of IF and ELSE.Though I have written the way what you asked me to but still unable to get values of VAR2 and VAR3 on cmd. – POOJA SINGH May 04 '20 at 06:26
  • @POOJASINGH My bad, make that `endlocal & set "var2=%var2%"` instead. – dxiv May 04 '20 at 06:34
  • 1
    @POOJASINGH Should work if you (i) remove the `exit /b` part, and (ii) leave just one `endlocal & set ...` line right above `:Result`. – dxiv May 04 '20 at 07:34
  • @dxiv BUT when VAR is not defined, even than :RESULT section is getting executed. And Also when VAR != value, even than :RESULT section is getting executed. I have updated your suggestion in the above code. – POOJA SINGH May 04 '20 at 09:01
  • @POOJASINGH The way you have it now `:Result` gets executed in all cases, possibly twice when also `call`'d from the `if defined var` block. If you want to only *call* it, and not also fall through to it at the end, then add a `goto :eof` line before `:Results`.. – dxiv May 04 '20 at 14:19
  • @POOJASINGH The line `endlocal & set "var2=%var2%"` will keep the value of `var2`outside the `setlocal` block (see [this](https://stackoverflow.com/questions/3262287/make-an-environment-variable-survive-endlocal) for example). How you set the variables *inside* the `setlocal` block is a different story, and if you have problems there you should ask a new question. – dxiv May 04 '20 at 20:03
  • Actually i got the solution to my problem but unable to answer, so am i supposed to delete this post?? – POOJA SINGH May 05 '20 at 05:44
  • POOJASINGH, You may post your answer if you wish, accept another answer or delete the post if you consider it a mistake. That is your choice. The post has been reopened. – michael_heath May 05 '20 at 05:57

2 Answers2

1

You should move your :Result block outside of the if blocks (just above :END would be a suitable spot for example; just put a goto End before the :Resultblock to not unwanted run into this). And then call :Result not goto Result inside the if block.
For further documentation execute call /? on the command line (and maybe goto /? for reference). This works with all other commands as well, set /?, if /? for example, and so on.

Since I cannot see where you set a value to VAR your current condition if defined VAR will always be false. So I think your script needs more care than moving the Result block. Or it is just a simplified example, then nevermind ;)
Maybe put an echo %VAR% before the if condition for debugging and to verify that there is a value.

For debugging purposes, try an @ECHO ON in the first line. That gives you all the steps your batch file takes and helps finding errors.

Update after your second Code Update:

Try a structure like this:

[...]

goto eof
:Result
  ... your result block here
goto eof

[...]

:eof

With this you guard your :Result block from being executed when the interpreter just runs from top to bottom.
Also I would suggest not using ampersand chains (&). Prefer one command in each line if possible.
You missed to add all the % symbols. The code you posted just does not make any sense without them.
Also it seems that you deleted the :Result block entirely but you still call it...
I am confused.

Please check other sources for help, like for example www.ss64.com (CMD) and some tutorials maybe. I won't update my answer another time, sorry. This question was closed anyway.

Antares
  • 605
  • 3
  • 14
  • I have done all the changes mentioned by you and updated the code in question, but still facing the issue. – POOJA SINGH May 01 '20 at 21:11
  • Nah, the updated code in your question is not changed the way I described it ;) Right now your control flow just goes from top to bottom and executes the :Result block and goes to End, everything after that is never executed. Put an `echo on` instead of `echo off` and see the trace through your code. Note that `:Result` is in no way a "barrier" of somekind. The controlflow will not "stop" there. It just executes all lines there are and acts according to it. – Antares May 02 '20 at 00:38
  • See my Update in the answer above. This will be my last update, though. I'm sorry. – Antares May 05 '20 at 04:58
  • Actually i got the solution but unable to answer on this post so should i delete this post ??? – POOJA SINGH May 05 '20 at 05:42
  • Deleting would be one way to go. Or you edit your question text. Currently the question is "locked/closed" and it is not allowed to add any answers to it, unless the question is made more clear. May be you just can accept any of the answers as helpful/solution and so the question would be in "finished" state. – Antares May 05 '20 at 05:46
1
@ECHO ON
SET "ABC=IQ"
SET "VAR=value"
ECHO(%VAR%

VERIFY OTHER 2>nul

SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (
    ECHO Unable to enable extensions
)

IF DEFINED VAR (
    IF "%VAR%" == "code" call :Result
    IF "%VAR%" == "code2" call :Result
    IF "%VAR%" == "value" call :Result
    SET "VAR2=C:\abc\files"
) ELSE (
    SET "VAR2=C:\abc\file\pic" & ECHO VAR not defined
)

rem Set VAR2, VAR3 and NAME outside the current local scope.
ENDLOCAL & (
    SET "VAR2=%VAR2%"
    SET "VAR3=val"
    SET "NAME=%NAME%"
)

rem Display variables set beginning with VAR and NAME.
SET VAR
SET NAME

rem End the code here to prevent continuing into the following label.
EXIT /B 0

:Result
    SET "NAME=CODE" & SET "VAR2=C:\abc\file"

Added double quotes around the SET command names and values to prevent trailing whitespace being included.

VAR2 and VAR3 set with same parsed code as ENDLOCAL so they are available in the global scope. This works as the parsed code replaces %VAR2% with it's value before the execution of SETLOCAL and the assignment done by the SET commands.

Added EXIT /B 0 to end the code so that :Result is not executed at the end of the code.

Output of SET VAR:

VAR=value
VAR2=C:\abc\files
VAR3=val

If VAR is undefined by removing the line SET "VAR=value":

VAR2=C:\abc\file\pic
VAR3=val

Many of the commands have help information so can use command /?. Command can be example set /?.

michael_heath
  • 5,262
  • 2
  • 12
  • 22