-1

What I am doing wrong here please? I want to make a windows batch file that will call an exe, passing in some arguments and assign the return value to a variable. I have tried lots of different variations of the following but I cant make it work.

SET EXE="path\to\exe"
SET TARGET_FILE="path\to\file\to\be\read\by\exe"

for /f %%i in (%EXE% -arg1 %TARGET_FILE%) do set VAR=%%i

ECHO %VAR%
PAUSE

What am I missing? In case it matters, the two paths above will probably contain spaces, line C:\Program Files\etc.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Aenaon
  • 3,169
  • 4
  • 32
  • 60
  • What do you mean by the "return value" of the `exe`? Are you taking about the exit status or the standard output of the `exe`? – RobertBaron May 24 '19 at 22:46
  • not the exit status. For example the `exe` can be small application that reads a photo and returns its width (or height) – Aenaon May 24 '19 at 22:49
  • 1
    Would it be too difficult to post the actual content you're assigning to `%EXE%` and `%TARGET%`? – Compo May 24 '19 at 23:44

2 Answers2

1

The following batch file should work. I have not tested, let me know if it does not.

SET EXE="path\to\exe"
SET TARGET_FILE="path\to\file\to\be\read\by\exe"

for /f "delims=" %%i in ('"%EXE% -arg1 %TARGET_FILE%"') do (
echo %%i
)
RobertBaron
  • 2,817
  • 1
  • 12
  • 19
  • The title requests to set a variable. For a single command a (code block) isn't necessary. If echo is replaced with `set var=%%i` only the last line of a multi line output will persist. –  May 24 '19 at 23:26
  • @Robert: It is not working for some reason. I had similar messages when I was trying my own script. With you script, when the path has spaces I get `C:\Programs is not recognized as an internal or external command, operable program or batch file.`. When I move everything in a location with no spaces in the path names i get `The filename, directory name, or volume label syntax is incorrect.`. In any case, thanks for your help! – Aenaon May 24 '19 at 23:30
  • You need to add double quotes around `%EXE%`. I edited the answer. – RobertBaron May 24 '19 at 23:40
  • @Robert: Ah yes! I think i got it. Inside the parentheses you need to have: `'"%EXE% -arg1 %IMG%"'`. ie single quote followed by a double quote after the opening parenthesis, matched by a double quote and a single quote just before closing parenthesis. That works on both my code and yours. Could you please edit you answer, so i can accept it. Many thanks for looking in to that. – Aenaon May 25 '19 at 08:15
  • I had missed the fact that `TARGET_FILE` could contain spaces. – RobertBaron May 25 '19 at 08:28
1

First, please read my answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? It makes a big difference if first double quote is left to variable name or right to equal sign on definition of an environment variable. See also How to set environment variables with spaces?

Let us look on this code:

@echo off
set "Executable=path\to\exe"
set "TargetFile=path\to\file\to\be\read\by\exe"

for /F delims^=^ eol^= %%I in ('"%Executable%" -arg1 "%TargetFile%" 2^>^&1') do set "Data=%%I" & goto HaveData

echo No data captured!
pause
goto :EOF

:HaveData
echo Data: %Data%
pause

FOR with option /F with string in round brackets enclosed in straight single quotes results in starting in background cmd.exe /c with using %ComSpec% /c with the string in round brackets as additional arguments. So one more command process is started by FOR in background to execute the specified command line between '...' inside the parentheses.

The full qualified file name was first assigned to an environment variable without the double quotes needed on this string containing a space or one of these characters &()[]{}^=;!'+,`~. So the reference of the environment variable Executable must be now enclosed in double quotes. The same needs to be done for TargetFile.

FOR captures everything written to handle STDOUT of the started command process for being finally processed line by line after started cmd.exe terminated itself. The output to handle STDERR is also captured by FOR, but is just redirected to STDERR of the command process executing the batch file and therefore would be just displayed in console window.

But the executable perhaps outputs the information of interest to handle STDERR instead of STDOUT. For that reason 2>&1 is used as documented by Microsoft in article about using command redirection operators to get output of executable written to STDERR redirected to STDOUT of background command process.

The redirection operators > and & must be escaped with caret character ^ on FOR command line to be interpreted as literal characters when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line with using a separate command process started in background.

FOR processes the captured output line by line with skipping all empty lines after started executable finished and so started cmd.exe finished, too.

By default lines starting with ; are also ignored by FOR as the semicolon is the default end of line character. eol= is specified to define no end of line character to avoid ignoring any non-empty line.

FOR splits up by default a line into substrings (tokens) using normal space and horizontal tab character as string delimiters. This string splitting behavior is most likely not wanted here. For that reason delims= is specified for an empty list of delimiters to disable line splitting behavior and get assigned to specified loop variable I the entire non-empty line currently processed by FOR.

The options list after for /F is usually specified with using "one or mor options". This is not possible here to define an empty list of delimiters and no end of line character. So the options are specified not enclosed in a double quoted string. But in this case = and space must be escaped with ^ to be interpreted as literal characters and not as argument separators by cmd.exe parsing this FOR command line to pass delims= eol= as one argument string to command FOR.

So if the executable defined with environment variable Executable outputs just one non-empty line in ANSI, this line is assigned to environment variable Data.

But perhaps the executable outputs the information of interest not in ASCII/ANSI, but in Unicode with UTF-16 Little Endian encoding and additionally outputs two or more empty lines as for example wmic.exe does. In this case a bug of FOR on interpreting the Unicode encoded output must be taken into account which results in deletion of environment variable Data after being defined with the data of interest on FOR processing wrong the UTF-16 LE encoded empty lines at end of captured Unicode output. For details about this bug of FOR see How to correct variable overwriting misbehavior when parsing output? The solution used here is to leave the loop after first non-empty line is assigned to environment variable Data by a jump to code below the label HaveData.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • for /?
  • goto /?
  • pause /?
  • set /?
Mofi
  • 46,139
  • 17
  • 80
  • 143