Reputation: 43
I'm new in batch, and therefor I can't figure out, why I am getting a syntax error??
This is my code:
set /p hostname1=<a.txt
echo %hostname1%
PAUSE
IF %hostname1% == 0 (
SET %hostname02% = 1
echo %hostname02% >> a.txt
PAUSE
)
IF %hostname1% == 1 (
SET %hostname03% = 2
echo %hostname03% >> a.txt
PAUSE
exit
)
IF %hostname1% == 2 (
echo MSGBOX "Message" > %temp%\TEMPmessage.vbs
call %temp%\TEMPmessage.vbs
del %temp%\TEMPmessage.vbs /f /q
)
This is just a "for fun" project, but i would like to understand why I am getting this annoying error!
Upvotes: 3
Views: 38803
Reputation: 49084
First, read answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains how to assign a string value correct to an environment variable. Wrong is set variable = value
which assigns SPACEvalue to an environment variable with name variableSPACE and for that reason there is no environment variable with name variable after this command line.
Completely wrong is in most cases also set %variable%=value
because of this command line assigns value to an environment variable with a name defined by value of the environment variable variable.
Second, all environment variable references done with syntax %variable%
within a command block starting with (
and ending with matching )
are expanded by current value of the environment variable before the command using the command block is executed at all. This means all %variable%
are replaced by current value of referenced environment variable which is nothing if the variable with name variable is not yet defined at all.
Let us look on what is really executed by cmd.exe
for a command block like:
set "hostname02="
set "hostname1=0"
IF %hostname1% == 0 (
SET %hostname02% = 1
echo %hostname02% >> a.txt
PAUSE
)
The really executed command lines are:
set "hostname02="
set "hostname1=0"
IF 0 == 0 (
SET = 1
echo 1>>a.txt
PAUSE
)
The result is an exit of execution of batch file by cmd.exe
with the error message:
Syntax error.
This can be seen by running the batch file without @echo off
or with @echo ON
from within a command prompt window instead of double clicking on the batch file. See also debugging a batch file.
A batch file programmer must always take into account how the command lines are really executed after processing the lines in batch script and not how they are written in the batch file, especially on usage of %variable%
which dynamically modifies the code during execution of the script.
A working code for the example code in question is:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist a.txt set /P hostname1=<a.txt
if not defined hostname1 set "hostname1=0"
echo hostname1 is: %hostname1%
if "%hostname1%" == "0" (
set hostname02=1
>>a.txt echo 1
) else if "%hostname1%" == "1" (
set hostname03=2
>>a.txt echo 2
goto EndBatch
) else if "%hostname1%" == "2" (
echo MSGBOX "Message">"%TEMP%\TEMPmessage.vbs"
%SystemRoot%\System32\wscript.exe "%TEMP%\TEMPmessage.vbs"
del "%TEMP%\TEMPmessage.vbs"
)
:EndBatch
endlocal
pause
This batch file first sets up a local environment with enabled command extensions as required here and delayed environment variable expansion disabled as not needed by the code below. The parameters EnableExtensions DisableDelayedExpansion
on usage of command setlocal
could be omitted because of command extensions are enabled by default and delayed expansion is disabled by default on starting a new command process as done on double clicking on a batch file. But it is always advisable to explicitly define the environment needed for a batch file. Read this answer for details about the commands SETLOCAL and ENDLOCAL.
The next line assigns first line of file a.txt
to environment variable hostname1
if this file exists at all in current directory which of course can be different to directory of the batch file depending on how the batch file was started for execution by cmd.exe
.
The command FOR with option /F
is usually used to read a text file line by line and assign strings read from the file to environment variables. But set /P variable=<file.txt
can be also used to just assign first line of file.xt
to environment variable variable
.
The fourth command line verifies if variable hostname1
is defined now which is not the case if the file a.txt
does not exist in current directory or this file starts with an empty line. The environment variable hostname1
is defined with value 0
if not defined after third line.
Next the current value of variable hostname1
is output for visual verification.
Then three IF conditions are used to run case-sensitive string comparisons. The strings to compare are enclosed in double quotes which makes the batch file more fail safe against exit of execution because of a syntax error depending on string read from file a.txt
. But this solution is still not 100% fail safe, see answer on How to stop Windows command interpreter from quitting batch file execution on an incorrect user input? for details on how to get a batch file code fail safe on usage of set /P
with string value entered by a user or read from a file which every user can edit before running the batch file.
The string values assigned to hostname02
and hostname03
are fixed in code and therefore those string values can be directly written also into file a.txt
without the need to reference the environment variables hostname02
and hostname03
defined inside the command blocks which would required delayed environment variable expansion.
The redirection operator >>
and the file name are written at beginning of a line to really write into file a.txt
just 1
or 2
without a trailing space as long as there are no trailing spaces on the two echo
command lines in the batch file. On usage of echo 1 >>a.txt
the space between 1
and >>
would be also written into file a.txt
. And echo 1>>a.txt
would not write 1
at all into file a.txt
. For details read the Microsoft article about Using command redirection operators. Windows command processor reformats >>a.txt echo 1
to echo 1 1>>a.txt
before execution of this command line. So >>a.txt
at beginning of the line after the indent spaces for better readability is moved by Windows command interpreter on parsing to end of the command line with inserting a 1
(space and one) left to redirection operator >>
.
A VBScript is executed either with cscript.exe
– console version of Windows scripting host – or with wscript.exe
– GUI version of Windows scripting host. The command CALL is not the right command to execute a VBScript. So the batch file uses wscript.exe
to run the VBScript showing just a simple message box.
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.
del /?
echo /?
endlocal /?
goto /?
if /?
pause /?
set /?
setlocal /?
wscript /?
Upvotes: 5
Reputation: 57252
set /p hostname1=<a.txt
echo %hostname1%
PAUSE
:: this will check if the string hostname1 is "0"
IF "%hostname1%" == "0" (
SET "hostname02=1"
echo !hostname02! >> a.txt
PAUSE
)
IF %hostname1% == 1 (
SET "hostname03=2"
echo !hostname03! >> a.txt
PAUSE
exit
)
IF %hostname1% == 2 (
echo MSGBOX "Message" > %temp%\TEMPmessage.vbs
call %temp%\TEMPmessage.vbs
del %temp%\TEMPmessage.vbs /f /q
)
try like this.
Upvotes: 1