运行时我的批处理窗口关闭(如果存在) [英] My batch window closes when running if exist

查看:49
本文介绍了运行时我的批处理窗口关闭(如果存在)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小程序,当我运行如果存在"时,它将关闭,有人可以告诉我为什么吗?我已经检查了语法错误,没有(我认为),我将在这里粘贴我的代码,看看你能做什么.

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?

推荐答案

导致脚本提前退出的问题是else分支的最后一个if语句中的语法错误.如果您从命令行运行脚本(而不是双击脚本),则会收到错误消息:

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"这一次是意外的.

="y" was unexpected at this time.

实际上,您的最后一个if语句是:

Indeed your last if-statement is:

    if "%yesnol%"="y" (

但是cmd解析器希望使用双"="符号(==)进行比较,因此您应该具有:

but the cmd parser expects a double "=" sign (==) for comparisons, so you should have:

    if "%yesnol%"=="y" (

即使不使用else分支也能看到它的原因是因为if块(实际上,所有由( ... )分隔的代码块)被解析为好像是一个写在上面的单个命令一行(块中的每个子命令"均用&&分隔).由于解析器将一次性处理整个行",因此它将检测出整个块中存在的任何语法错误.

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.

除了语法错误之外,您在脚本中还犯了一些小错误.第一个是在代码块内声明标签实际上不是很好.您已经在else分支的if块内声明了:yes标签. if块中的goto将破坏" if-上下文.您可能不会在代码中注意到,但请考虑以下示例:

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

您期望输出

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

但输出将是

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"

goto破坏了if上下文.如前所述,cmd解析器将把整个if块解析为一个命令.这样看:您要让解析器放弃它正在处理的命令(带有刚刚检查过的条件的整个if块),然后跳转到其他地方.那是在if条件之后的其他地方,因此它甚至不会再次评估该条件.因此,一旦您进入了一个块(尤其是if块和 for循环),就不会" t使用goto忽略该块中的某些代码,使用if语句,然后将要忽略的代码放入if块中. goto跳转到代码块之外不是问题,但是例如从标签位于if块内部的那一刻起,它可能会导致意外结果.

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.

第二个错误与变量YesNoInyesnol有关.就像我说的那样,整个if块是作为一个命令一次性解析的.不可能给变量一个新值,并且不能在同一命令中使用简单变量扩展%YesNoIn%%yesnol%读取该新值.解决此问题的方法是延迟扩展(该链接也有示例).在我编写此答案的过程中,我看到@Josefz已经发布了答案,但扩展存在延迟,因此在此我不再赘述.但是我建议您看一下 choice 命令.使用choice命令,您将不需要延迟扩展.它只是设置错误级别,并且存在一种检查错误级别而无需担心延迟扩展的方法: IF ERRORLEVEL n 将检查错误级别是否大于或等于n .最重要的是,choice会自动验证用户是否输入了正确的值!
使用choice而不是set /p的脚本将如下所示:

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:使用choice时无需按Enter键.

PS: No Enter key needs to be pressed when choice is used.

编辑:第三个​​错误是选择变量APPDATA,您的Windows操作系统已在用户上下文中使用了该变量,如您所见

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.

这篇关于运行时我的批处理窗口关闭(如果存在)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆