1

i start a batch file to process some code, at a time it calls another batchfile and should get returned a variable, but the methods explained in man pages about local/endlocal seem not to work here, what am i doin wrong please?

first batch file:

@ECHO OFF
setlocal
call secondbatchfile.bat xyz
echo. [%val1%]

second batch file:

@if (@a==@b) @end /*                        <== btw what does this code do ???
@echo off
setlocal enabledelayedexpansion
set "URL=%~1"
set bla bla ...
do bla bla ...

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (

rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"

rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^to[a-z]*=[0-9]*" >NUL && (

rem test was successful.  Scrape number.
for /f "tokens=2 delims==" %%x in ("%%I") do set "val1=%%x"

echo !val1!                            <== this works
ENDLOCAL & SET top=%val1%              <== this not

)
)

this results in:

c:\test>firstbatchfile.bat
123456789                                   <== this works
 []                                         <== this not

i tried different syntax of return var like !val1! or %%val1 - none worked. what am i missing?

UPDATE: regarding to other example here on site i tried:

call seconbatchfile.bat xyz ret1
echo. [%2%] [%ret1%]

and in secon file changed:

rem ENDLOCAL & SET %2=!val1!

does not work either?

SOLUTION:

second batch file can be origin script from rojo reading out the whole website, i did leave the trim and match syntax lines to only return relevant matches:

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (

rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"

rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^[a-z]*=[0-9]*" >NUL && (

echo(%%I

)
)

and the first batch file calling it will do the search for two needed parameters like this:

@ECHO OFF
setlocal
for /f "delims=" %%I in ('secondbatchfile.bat "http://xyz"') do (

echo %%I | findstr /i "top" >NUL && (

for /f "tokens=2 delims==" %%x in ("%%I") do (
set "updir=%%x"
)
)
echo %%I | findstr /i "low" >NUL && (

for /f "tokens=2 delims==" %%x in ("%%I") do (
set "lowdir=%%x"
)
)
)

echo.[%updir%]
echo.[%lowdir%]

many thanks to rojo for fantastic code

Community
  • 1
  • 1
peet
  • 274
  • 3
  • 5
  • 18
  • why don't just set environment variable in the inner batch? like this `set RETURNVALUE=your_value` – shibormot Mar 21 '13 at 23:47
  • The `@if` line does precisely nothing since the string `(@a` can never be equal to the string `@b)`. The leading `@` suppresses the echo-statement-to-console for that ONE statement. It probably can be safely deleted, unless some really obscure method is being used, like some other [batch?] program trying to find that string within the .bat source. – Magoo Mar 22 '13 at 05:16
  • but it is set in the inner batch, doesn't it? in the third-last line `do set val1=%%x` - if i take out the endlocal piece of code the result is empty in calling batch either? – peet Mar 22 '13 at 06:25
  • [the @a comes from here](http://stackoverflow.com/questions/15395490/batch-script-get-html-site-and-parse-content) – peet Mar 22 '13 at 06:35
  • Peter is right, that first line does nothing - in batch BUT: the FOR -command calls the very same file (jscript "%~f0") as a Java-Script. And Java interpretes the /* as beginning of a comment (like REM). There should be an */ elsewhere in your script to indicate an "EndComment" - just before the java-code starts. Thus you can use the same file as Batch and as Java script – Stephan Mar 22 '13 at 08:47

2 Answers2

2

The easiest solution is to have your second batch file echo its result, and capture it using a for loop in the first batch file. Cancelling your setlocal to pass an environment variable back to the calling script is a messy affair.

first.bat:

@echo off
setlocal

for %%x in (
    "http://10.0.0.1/foo/vars.txt"
    "http://10.0.0.1/bar/vars.txt"
    "http://10.0.0.1/baz/vars.txt"
    "http://10.0.0.1/qux/vars.txt"
    "http://10.0.0.1/corge/vars.txt"
) do (
    for /f "delims=" %%I in ('fetchvalue.bat "%%~x"') do (
        set "val1=%%I"
    )
    echo.[%val1%]
)

fetchvalue.bat:

@if (@a==@b) @end /*

:: fetchvalue.bat <url>
:: output the "value" part of variable=value from a text file served by http

@echo off
setlocal
if "%~1"=="" goto usage
echo "%~1" | findstr /i "https*://" >NUL || goto usage

set "URL=%~1"

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (

    rem trim whitespace from beginning and end of line
    for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"

    rem test that trimmed line matches "variable=number"
    echo !line! | findstr /i "^to[a-z]*=[0-9]*" >NUL && (

        rem test was successful.  Scrape number.
        for /f "tokens=2 delims==" %%x in ("%%I") do echo(%%x
    )
)

goto :EOF

:usage
echo Usage: %~nx0 URL
echo     for example: %~nx0 http://www.google.com/
echo;
echo The URL must be fully qualified, including the http:// or https://
goto :EOF

JScript */
var x=new ActiveXObject("Microsoft.XMLHTTP");
x.open("GET",WSH.Arguments(0),true);
x.setRequestHeader('User-Agent','XMLHTTP/1.0');
x.send('');
while (x.readyState!=4) {WSH.Sleep(50)};
WSH.Echo(x.responseText);

Here's an example first.bat that will sort the fetched values, set low to the lowest value, and set high to the highest.

@echo off
setlocal enabledelayedexpansion

for %%x in (
    "http://10.0.0.1/foo/vars.txt"
    "http://10.0.0.1/bar/vars.txt"
    "http://10.0.0.1/baz/vars.txt"
    "http://10.0.0.1/qux/vars.txt"
    "http://10.0.0.1/corge/vars.txt"
) do (
    set low=
    for /f "delims=" %%I in ('fetchvalue.bat "%%~x" ^| sort') do (
        if not defined low set "low=%%I"
        set "high=%%I"
    )
    echo low: !low!
    echo high: !high!
)
rojo
  • 24,000
  • 5
  • 55
  • 101
  • wow, so in my example at top i would need to use %%I to catch the echoed result of parse? i need the modularity because the first file does a loop over about 15 devices and does process different action on all of them. for one of those actions i need the result of your genious http script. at least i would need to be able to call it as a function in the first script while i thought it would be easyer to read if not to overloaded. as a function call would then be the better way in your eyes? – peet Mar 22 '13 at 19:08
  • @peet - Ah, OK. I took out the combined example. I also updated the example `first.bat` to illustrate how you can use a `for` loop to supply another `for` loop with its URL. – rojo Mar 22 '13 at 19:29
  • did i get it right that i need a function which calls the other batchfile to use the returned var? i tried your code which works for shure, as i only need two vars of findable 10 ones i was thinkin about to double it, one for each searched (needed) value top and low. is there another easy function to use sencefully other than a for loop - or i might have to expand to return and set both needed values maybe? anyway great thanks or your input and efforts. – peet Mar 22 '13 at 19:51
  • @peet - Sorry bud, but I'm not sure what you're asking. Are you asking whether it's required that you use an external batch script to fetch the values you need? No, it's not required. For the rest of your question, I think I need someone to translate `two vars of findable 10 ones i was thinkin about to double it` into English for me. :> – rojo Mar 22 '13 at 19:57
  • sorry, i meant that i do need a function like the `for (call fetch.bat)` to catch fetch.bat's return without ending `setlocal` which would allow values to keep persistent till other script runs and accidently uses it maybe. the second part i meant, that the fetch.bat (your http script) will parse about 10 parameters of which i do need only 2. and to keep it simple i was thinkin about to double your http script in two bat's (one for each var) which could be easyer for me rather than finding two parameters in one fetch.bat run and returning 2 needed (of 10 found) values. – peet Mar 22 '13 at 20:20
  • wow, i did write the second last comment on your first answer while you already adapted and changed code meanwhile - i'll get an better script scrape of mine in a minute – peet Mar 22 '13 at 20:28
  • @peet - Are you asking for a way to obtain the lowest and the highest value from the fetched values? If that's what you're asking, I added an example showing how to do that. – rojo Mar 22 '13 at 20:36
  • no my searched two values only depend on their naming top and low, i added the script skelleton, this might be useful for others maybe too – peet Mar 22 '13 at 20:44
  • have to mention very smart way to set the two values to highest and lowest values, thanks for that idea – peet Mar 22 '13 at 20:51
0

Your inner batch file is ending by setting an environment variable named top: set top=%val1%. You'll need to change that to set val1=%val1%.

...
echo !val1!
ENDLOCAL & SET val1=%val1%
Nate Hekman
  • 6,507
  • 27
  • 30