Malthe Reipurth
Malthe Reipurth

Reputation: 43

The syntax of the command is incorrect?

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

Answers (2)

Mofi
Mofi

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.exeGUI 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

npocmaka
npocmaka

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

Related Questions