You start a new command shell with every system
call; variables you declare exist only in that command shell.
Unfortunately I was not able to find out how to use variables in system
calls directly.1
Furtunately though, @aschipfl knew the answer and posted it as comment (thanks!). The reason set a=abc && echo %a%
does not work (also not when you type it in a console) is that %a%
is evaluated when the command is parsed, that is, before the set
command has been executed. At that point the variable is not set. Calling cmd
with "delayed expansion" enabled switches the evaluation time to execution time; when the echo
is encountered the variable is defined and will be printed.
The option to activate delayed evaluation is /V
. cmd /?
prints the following:
/V:ON Enable delayed environment variable expansion using ! as the
delimiter. For example, /V:ON would allow !var! to expand the
variable var at execution time. The var syntax expands variables
at input time, which is quite a different thing when inside of a FOR
loop.
So this will work:
#include <cstdlib>
using namespace std;
int main()
{
system("cmd /V:ON /C set a=abcd ^&^& echo !a!");
return 0;
}
Another solution could be to let your program create a temporary batch file and then execute that file in a single trivial system
command. The strategy to move complicated scripts in files is recommended in general for Windows because it avoids command line parsing by cmd
which is notoriously hard to get right (here is a Microsoft blog diving into the details).
#include <cstdlib>
#include <fstream>
using namespace std;
int main()
{
ofstream batchfile{ "tmpbatchfile.bat" };
batchfile << "set x=abc\n";
batchfile << "echo %x%\n";
batchfile << "pause\n";
system("tmpbatchfile.bat");
return 0;
}
Note that the system
call appears to return before the command has finished. This makes it impossible to delete the temporary file.
1One should think that passing a string with more than one command — multi-line or &&
-chained — would do the trick, but I cannot get it to work.
For example system("echo abc && echo ****");
works; but system("set a=abc && echo %a%");
does not (it prints a literal %a%
).