I found a GUI app on Github that I'm using to store command lines to run. The author is using the following syntax to take what I enter and use it in a cmd window -
I enter into his form -
set "test=four"
echo %test%
pause
He converts it to this and it fails to show the contents of the variable -
"C:\Windows\System32\cmd.exe" /Kset "test=four"&&echo %test%&&pause
The result is %test%, not the contents of the test variable, which is four.
If I run his command line in a cmd window myself, it also fails to get the var contents and shows %test%.
So why is this not working and I suggested to him to just copy what I entered into his form and do a paste into the cmd window he generates and run it. Can that be coded easily and is that the easiest fix?
CodePudding user response:
TL;DR: Use cmd /v:on /k (set "test=four" ^& echo !test! ^& pause)
Read How does the Windows Command Interpreter (CMD.EXE) parse scripts? for additional information about what's going on.
I want to preface this by saying that chaining commands to be on the same line is always a bad idea. You're allowed to run commands on multiple lines for a reason, and you should take advantage of this; it makes things easier to read and it makes the script behave better.
That said, there is a way to do this, but your code has multiple things keeping it from working.
First of all, &&
is meant for only running the second command when the first command succeeds. Neither cmd
nor echo
will ever fail, so you only need &
here. echo %test%
is running separately from the rest of your code because the way that the interpreter is reading your code, it thinks that you only want to run "C:\Windows\System32\cmd.exe" /Kset "test=four"
and then run echo %test%
once that comes back successfully. In order to run all three commands in the same instance of cmd, you need to use parentheses so that everything gets treated as a single command.
Additionally, in order to tell the interpreter that &
isn't meant to be used to chain commands until the new cmd
instance is running, you need to escape them with ^
.
Finally, because you're trying to set and use a variable on the same line, the interpreter tries to replace %test%
with its value when it first gets read in before the value has a chance to get set. To get around this, you need to enable delayed expansion by using the /V:on
flag and then use !test!
so that the variable doesn't get expanded until execution time.