1

I'm writing a batch command script where in there is a check for Environment variables. I need to write a FOR loop by passing all the required variables and then validate if it is defined or not and if it is not defined then prompt the value for that key and set that variable permanently.

Problem is that I could not dereference the loop variable and check it in Environment variable.

Sample code is as below:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%G IN (JBOSS_HOME, JAVA_HOME, ANT_HOME, PERFORCE_PATH, P4CLIENT) DO (
  ECHO.
  ECHO. Loop Item : %%G
  :: Call a function by sending each value to check if it is set in ENVIRONMENT Variables, if not then add it persistently.
  CALL:validateAndUpdate %%G
)
GOTO:EOF

:validateAndUpdate
  :: Now I have to check if passed value is available in ENVIRONMENT variable or not
  :: echo %~1 will print value like JBOSS_HOME 
  :: Below IF condition always substitues to IF ("JBOSS_HOME" == []) and it always returns true
  :: but could not find syntax to use it to DE-reference and check if that key is set.
  :: Ex: IF %JBOSS_HOME% == []

  IF ("%~1" == []) (
    ECHO.
    ECHO. %~1 is empty
    SET /p value="Enter value for '%~1' : "

    :: Set that key value pair persistently using SETX
    SETX %~1 "%value%" 
  ) ELSE (
    ECHO.
    ECHO. %~1 is available as ENVIRONMENT variable
  )

GOTO:EOF

ENDLOCAL
Chandre Gowda
  • 870
  • 1
  • 7
  • 24
  • I got the half solutoin, instead of `IF ("%~1" == [])` need to use `IF("!%~1!" == [])` – Chandre Gowda Dec 14 '14 at 23:52
  • It is returning true even if the variable is not defined. Tried with `IF ("!%~1!" == "")` too, but still it goes to `ELSE` condition – Chandre Gowda Dec 15 '14 at 00:09
  • Should be `IF "!%~1!"==""` Note no `==` surrounding spaces, no parentheses. That `!%~1!` is the variable _value_, `%~1` is variable _name_ – JosefZ Dec 15 '14 at 00:10
  • @JosefZ, thanks for your reply, I tried with `IF !%~1!=="" (` did not help, it still goes to ELSE condition – Chandre Gowda Dec 15 '14 at 00:17
  • Read carefully: `IF "!%~1!"==""` not `IF !%~1!==""` Note double guotes – JosefZ Dec 15 '14 at 00:20
  • My Bad, Thanks JosefZ.. it indeed worked now. – Chandre Gowda Dec 15 '14 at 00:23
  • You also need to insert `rem` in front of your `:: Call a function` type comments within your `for` and `if` loops if you intend to keep them. Labels have unpredictable results within loops, including labels used as remarks. – rojo Dec 15 '14 at 00:44

2 Answers2

2

To check whether a variable is defined, use the defined keyword in an if statement. help if for more information.

If I may make another suggestion, it might be better to display a folder chooser for the user rather than asking him to key pathnames manually. To that end, save this proof of concept with a .bat extension and try it out. See whether it works like you want:

@if (@a==@b) @end   /* JScript multiline comment

:: based on https://stackoverflow.com/a/15906994/1683264
:: batch portion

@echo off
setlocal enabledelayedexpansion

for %%G in (windir, temp, foo, bar) do (
    if not defined %%G (
        call :chooser %%G "Locate directory for %%G."
    ) else echo %%G is already defined as !%%G!
)

goto :EOF

:chooser <var_to_set> <dialog_title>
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%~2"') do (

    rem :: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    rem :: Remove the "echo" from this next line when you are satisfied
    rem :: that it will do what you intend.
    rem :: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    echo setx %~1 "%%~I"

)
goto :EOF

:: JScript portion */

var shl = new ActiveXObject("Shell.Application");
var folder = shl.BrowseForFolder(0, WSH.Arguments(0), 0, 0x00);
WSH.Echo(folder ? folder.self.path : '');

After you're satisfied the simulation does what you intend, remove echo from the :chooser subroutine.

See this page for more methods of launching a file or folder chooser from a .bat script, and see this GitHub Gist for more details and more examples of JScript / batch hybrids.

Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101
  • thanks for this sample, though it is not exactly what I needed, I can use it in situations where there is a necessary to choose the folder. Because some of the Environment variables are just key value pairs and not exactly the folders. – Chandre Gowda Dec 17 '14 at 11:52
1
@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%g in (JBOSS_HOME, JAVA_HOME, ANT_HOME, PERFORCE_PATH, P4CLIENT) do (
        echo(
        echo Testing %%g
        if defined %%g (
            echo %%g is available as ENVIRONMENT variable
        ) else (
            echo %%g is empty
            set /p "value=Enter value for '%%g' : " && (
                setlocal enabledelayedexpansion
                for /f "delims=" %%v in ("!value!") do (
                    endlocal 
                    SETX %%g "%%v"
                )
            )
        )
    )

As already indicated, if defined varname is the "correct" way to check if a variable is defined.

MC ND
  • 69,615
  • 8
  • 84
  • 126
  • Just curious, and Google wasn't illuminating on the matter. What is the advantage of avoiding `enabledelayedexpansion` until a `!var!` is needed; or, what is the disadvantage of letting the entire script run under `enabledelayedexpansion`? I typically don't include `enabledelayedexpansion` if my script doesn't contain any delayed vars. But if there's at least one delayed var, even if it's at the end of of the script, I always poke `enabledelayedexpansion` just below `@echo off` at the top and leave it there. Why is this bad? Have I been living a lie all my life? – rojo Dec 17 '14 at 13:16
  • @rojo, run this inside a batch file: `setlocal enabledelayedexpansion`, `set "data=this is a test !!!"`, `echo !data!` . What you will see is that `!` becomes a added problem to handle. – MC ND Dec 17 '14 at 13:24
  • Thanks! Nice hat on your gravatar, by the way. – rojo Dec 17 '14 at 13:34