I have a little program and when i run "if exist" it closes, can somebody tell me why? I have checked for syntax errors and none (i think), i will paste my code here and see what you can do.
echo What drive would you like to launch MCEdit on?
set /p DRIVE="Drive: "
if exist "%DRIVE%:\MC\DATA\mcedit\mcedit.exe" (
set APPDATA=%DRIVE%:\MC\DATA
start %DRIVE%:\MC\DATA\mcedit\mcedit.exe
) else (
echo You do not have MCEdit installed on this drive, would you like to install it?
set /p YesNoIn="[y/n]: "
if "%YesNoIn%"=="y" goto:yes
goto:menu
:yes
echo Choose the "mcedit.exe" file from a current installation on your pc.
pause
call "%DRIVE%\MC\DATA\FileViewer.bat"
xcopy "%OutCD%" "%DRIVE%:\MC\DATA\mcedit" /E
echo Done!
set /p yesnol="Would you like to launch MCEdit now? [y/n]: "
if "%yesnol%"="y" (
set APPDATA=%DRIVE%:\MC\DATA
start %DRIVE%:\MC\DATA\mcedit\mcedit.exe
)
)
Right after you type the drive it closes, any help?
The issue that causes the script to exit early is a syntax error in the last if-statement of your else
branch. If you run the script from the command line (not by double clicking on it) you'll get the error message:
="y" was unexpected at this time.
Indeed your last if-statement is:
if "%yesnol%"="y" (
but the cmd parser expects a double "=" sign (==
) for comparisons, so you should have:
if "%yesnol%"=="y" (
The reason why it will see it even if it won't take the else branch is because an if-block (actually, all block of codes delimited by ( ... )
) is parsed as if it was one single command written on one line (with each "subcommand" in your block separated with &&
). As the parser will process that whole "line" in one go, it will detect whatever syntax error present inside the whole block.
Besides that syntax error, there are some little mistakes you've made in your script. The first one is that it is actually not good to declare labels inside a block of code. You've declared the :yes
label inside the if-block in the else
branch. A goto
inside an if-block will "destroy" the if
-context. You maybe won't notice in your code, but consider this example:
@echo off
set var=Let's brake the if statement
IF DEFINED var (
echo The variable var exists
IF "%var%"=="Let's brake the if statement" goto :expected
echo The variable var is not what I would expect though.
echo You have to change it to something else...
goto :outside
:expected
echo I'm happy with its value. It is at least something I would expect
echo This is the end of the if-branch
) ELSE (
echo Strange ... the variable var is not defined.
echo Indeed: var="%var%"
)
:outside
rem just to get outside
You would expect an output like
The variable var exists
I'm happy with its value. It is at least something I would expect
This is the end of the if-branch
but the output will be
The variable var exists
I'm happy with its value. It is at least something I would expect
This is the end of the if-branch
Strange ... the variable var is not defined.
Indeed: var="Let's brake the if statement"
The goto
destroyed the if-context. As said earlier, the cmd parser will parse the whole if-block as one command. See it this way: you're asking the parser to abandon the command it was processing (the whole if
block with the condition it just checked) and jump to somewhere else. That somewhere else is after the if
condition, so it won't even evaluate that one again. So once you're inside a block (espacially if-blocks and for-loops) don't use goto
to ignore some piece of code inside that block, use if-statements and put the code to ignore inside the if-block. A goto
to jump outside a block of code is not a problem but from the moment the label is inside an if block for example, it can result in unexpected results.
The second mistake is about the variables YesNoIn
and yesnol
. As I said the whole if block is parsed in one go as one single command. It is not possible to give a variable a new value, and read that new value in the same command with the simple variable expansion %YesNoIn%
or %yesnol%
. A solution to this problem is delayed expansion (the link also has an example). As I was writing this answer, I saw @Josefz already posted an answer with delayed expansion so I won't repeat it here. But what I would recommend is that you take a look at the choice
command. Using the choice
command, you won't need delayed expansion. It just sets the errorlevel and there exists a way to check the errorlevel without worrying about delayed expansion: IF ERRORLEVEL n
will check if the errorlevel is greater or equal to n. On top of that, choice
automatically verifies if the user entered a correct value!
Your script with choice
instead of set /p
will look like this:
echo What drive would you like to launch MCEdit on?
set /p DRIVE="Drive: "
if exist "%DRIVE%:\MC\DATA\mcedit\mcedit.exe" (
set APPDATA=%DRIVE%:\MC\DATA
start %DRIVE%:\MC\DATA\mcedit\mcedit.exe
) else (
echo You do not have MCEdit installed on this drive, would you like to install it?
choice /c YN
REM Y ==> errorlevel = 1 ; N ==> errorlevel = 2
if ERRORLEVEL 2 goto:menu
echo Choose the "mcedit.exe" file from a current installation on your pc.
pause
call "%DRIVE%\MC\DATA\FileViewer.bat"
xcopy "%OutCD%" "%DRIVE%:\MC\DATA\mcedit" /E
echo Done!
choice /c YN /m "Would you like to launch MCEdit now? "
if NOT ERRORLEVEL 2 (
set APPDATA=%DRIVE%:\MC\DATA
start %DRIVE%:\MC\DATA\mcedit\mcedit.exe
)
)
PS: No Enter key needs to be pressed when choice
is used.
EDIT: A third mistake is the choice of the variable APPDATA
, it is already used by your windows OS in a user's context as you can see here.
You have simple typo in comparison operator in the latter if
. Correct to if "%yesnol%"=="y"
- I'm not sure whether changing
APPDATA
variable is a good idea.
- Missing
:menu
label in your code.
- Important: read and apply http://ss64.com/nt/delayedexpansion.html.
- Never use
:label
nor :: label-like comment
inside a command block enclosed in ()
parentheses
SETLOCAL EnableExtensions EnableDelayedExpansion
:::
:menu
:::
echo What drive would you like to launch MCEdit on?
set /p DRIVE="Drive: "
if exist "%DRIVE%:\MC\DATA\mcedit\mcedit.exe" (
set APPDATA=%DRIVE%:\MC\DATA
start %DRIVE%:\MC\DATA\mcedit\mcedit.exe
) else (
echo You do not have MCEdit installed on this drive, would you like to install it?
set /p YesNoIn="[y/n]: "
if /I "!YesNoIn!"=="y" (
echo Choose the "mcedit.exe" file from a current installation on your pc.
pause
call "%DRIVE%\MC\DATA\FileViewer.bat"
xcopy "%OutCD%" "%DRIVE%:\MC\DATA\mcedit" /E
echo Done^!
set /p yesnol="Would you like to launch MCEdit now? [y/n]: "
if /I "!yesnol!"="y" (
set APPDATA=%DRIVE%:\MC\DATA
start %DRIVE%:\MC\DATA\mcedit\mcedit.exe
)
) else goto:menu
)