【问题标题】:Detecting how a batch file was executed检测批处理文件的执行方式
【发布时间】:2008-12-18 09:58:05
【问题描述】:

假设 Windows,如果批处理文件是从打开的命令提示符或双击启动的,有没有一种方法可以从批处理文件中检测到?当且仅当它被双击时,我想在批处理结束时添加一个暂停,这样窗口就不会随着它可能产生的任何有用输出一起消失。

有什么聪明的方法可以做到这一点?我正在寻找可以依赖的解决方案,以便在或多或少使用默认设置配置的机器上工作。

【问题讨论】:

    标签: windows batch-file


    【解决方案1】:

    我刚刚进行了快速测试并注意到以下内容,这可能会对您有所帮助:

    • 从打开的命令提示符运行时,%0 变量的路径没有双引号。如果脚本位于当前目录中,则甚至没有给出路径,只给出了批处理文件名。
    • 从资源管理器运行时,%0 变量始终用双引号括起来,并包含批处理文件的完整路径。

    如果从命令控制台运行此脚本不会暂停,但如果在资源管理器中双击则会暂停:

    @echo off
    setlocal enableextensions
    
    set SCRIPT=%0
    set DQUOTE="
    
    @echo do something...
    
    @echo %SCRIPT:~0,1% | findstr /l %DQUOTE% > NUL
    if %ERRORLEVEL% EQU 0 set PAUSE_ON_CLOSE=1
    
    :EXIT
    if defined PAUSE_ON_CLOSE pause
    

    编辑: 从资源管理器运行时还有一些我无法解释的奇怪行为。原来,而不是

    @echo %SCRIPT:~0,1% | findstr /l %DQUOTE% > NUL
    if %ERRORLEVEL% EQU 0 set PAUSE_ON_CLOSE=1
    

    我尝试只使用if

    if %SCRIPT:0,1% == ^" set PAUSE_ON_CLOSE=1
    

    这在从打开的命令提示符运行时会起作用,但从资源管理器运行时会抱怨 if 语句不正确。

    【讨论】:

    • 另一个选项:%cmdcmdline% 提供用于启动当前 Cmd.exe 的确切命令行。从命令控制台启动时,此变量为“%SystemRoot%\system32.cmd.exe”。当从资源管理器启动时,这个 var 是 cmd /c ""[d:\path\script.bat]" "
    • 就个人而言,我确实会选择%cmdcmdline% 方法,但请注意,两个启动命令都可以在注册表中被覆盖!
    【解决方案2】:

    是的。 Patrick Cuff 的最后一个示例几乎可以工作,但是您需要添加一个额外的转义符 '^',以使其在所有情况下都有效。这对我很有用:

    set zero=%0
    if [^%zero:~0,1%] == [^"] pause
    

    但是,如果批处理文件的名称包含空格,则无论哪种情况都会被双引号引起来,因此此解决方案将不起作用。

    【讨论】:

      【解决方案3】:

      不要忽视拥有两个批处理文件的解决方案:
      abatfile.bat 和 abatfile-with-pause.bat
      第二个只是调用第一个并添加暂停

      【讨论】:

      • 但是如何找到调用哪一个呢?我认为这让我们回到了最初的问题?
      • 嗨学习。如果他们是从命令行运行的,他们会在没有暂停的情况下运行一个(因为输出仍然可见),如果他们通过双击运行,那么他们双击一个有暂停的那个,这样他们就可以看到结果然后关闭窗口
      【解决方案4】:

      这是我使用的:

      rem if double clicked it will pause
      for /f "tokens=2" %%# in ("%cmdcmdline%") do if /i "%%#" equ "/c" pause
      

      【讨论】:

        【解决方案5】:

        当我从脚本运行批处理文件时,我使用参数“automode”。

        set automode=%7
        

        (这里automode是给定的第七个参数。)

        下面是一些代码,当文件应该暂停时,我会这样做:

        if @%automode%==@ pause
        

        【讨论】:

          【解决方案6】:

          这里描述了一种简单的方法: http://steve-jansen.github.io/guides/windows-batch-scripting/part-10-advanced-tricks.html 链接中提到的代码几乎没有错字。这是正确的代码:

          @ECHO OFF
          SET interactive=0
          
          ECHO %CMDCMDLINE% | FINDSTR /L /I %COMSPEC% >NUL 2>&1
          IF %ERRORLEVEL%==0 SET interactive=1
          
          ECHO do work
          
          IF "%interactive%"==1 PAUSE
          EXIT /B 0
          

          【讨论】:

          • 这对我不起作用,如所写,如果脚本以“以管理员身份运行”开始......但添加不区分大小写的“/I” FINDSTR 命令的选项解决了这个问题。我发现 COMSPEC 有大小写差异。
          【解决方案7】:

          类似于第二个批处理文件,如果未给出某个参数(通过单击调用),您也可以暂停。

          这意味着只有一个批处理文件,但在从控制台调用时必须指定 -nopause 参数或类似的参数。

          【讨论】:

          • 这是最好的手动解决方案,但我真的希望有一个自动解决方案。也许在当前目录上分支,双击时可能是不变的。理想情况下,只需最少的设置即可在任何地方使用而无需使用快捷方式。
          【解决方案8】:

          疯狂的想法:使用任务列表并解析它的结果。 我在一个测试批处理文件中写过:

          任务列表 > test.out

          当我双击它时,在任务列表进程之前有一个额外的“cmd.exe”进程,当脚本从命令行运行时它不存在(但请注意,如果有人打开命令行shell,然后双击批处理文件)

          【讨论】:

            【解决方案9】:

            不管它是如何打开的,只添加暂停?如果它是从命令提示符打开的,除了无害的暂停之外不会造成任何伤害。 (不是解决方案,只是考虑暂停是否会如此有害/烦人)

            【讨论】:

            • 我认为这会很烦人,至少对我来说。当然必须有一些环境变量或状态设置存在于一个地方,而不是另一个我可以用来做出选择的地方!
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-07-28
            • 1970-01-01
            • 1970-01-01
            • 2013-03-01
            • 2016-09-09
            • 2012-12-26
            • 2013-07-29
            相关资源
            最近更新 更多