首页 文章

通过双击或从cmd窗口检测bat文件是否正在运行

提问于
浏览
20

我有一个bat文件可以执行大量操作并关闭cmd窗口,当用户双击来自资源管理器的bat文件时,这是很好的 . 但是,如果我从cmd> c:\ myfile.bat中已经打开的cmd窗口运行bat文件,那么我不希望bat文件关闭cmd窗口(END),因为我需要做其他事情 . 我需要bat dos命令代码,它会做类似的事情

if (initiated_from_explorer) then
else
endif

这可能吗 ?谢谢

10 回答

  • 2

    %cmdcmdline% 给出了用于启动当前Cmd.exe的确切命令行 .

    • 从命令控制台启动时,此var为 "%SystemRoot%\system32\cmd.exe" .

    • 从资源管理器启动时,此变量为 cmd /c ""{full_path_to_the_bat_file}" " ;
      这意味着您还可以检查bat文件中的 %0 变量,因为在这种情况下,它始终是bat文件的完整路径,并且始终用双引号括起来 .

    就个人而言,我会采用 %cmdcmdline% 方法(而不是 %O ),但要注意两个启动命令都可以在注册表中重写...

  • 2

    来自"mousio"的解决方案很不错;但是,由于 %cmdcmdline% 值的双引号(在 %cmdcmdline% 附近有或没有双引号),我个人无法使其在"IF"语句中工作 .

    但是,使用 %0 的解决方案可以正常工作 . 我使用了以下块语句,它就像一个魅力:

    IF %0 == "%~0"  pause
    

    希望它可以提供帮助 .

  • 11

    综合答案,源自此页面上的大部分信息:

    :pauseIfDoubleClicked
    setlocal enabledelayedexpansion
    set testl=%cmdcmdline:"=%
    set testr=!testl:%~nx0=!
    if not "%testl%" == "%testr%" pause
    
    • 变量"testl"获取cmd处理器调用的完整行(按照mousio),删除所有令人讨厌的双引号 .

    • 变量"testr"采用"testl"并进一步删除当前批处理文件名的名称(如果存在,则将通过双击调用批处理文件) .

    • if语句查看"testl"和"testr"是否不同 . 如果是,则双击批次,暂停;如果不是,则在命令行输入批处理,继续 .

    当然,如果您在检测到双击时想要执行其他操作,则可以更改暂停 .

    感谢大家 .

  • 4

    从CMD窗口运行时,您可以添加命令行参数,该窗口赢得了't exist when the file is double-clicked. If there is no parameter, close the window. If there is, don' t关闭它 . 您可以使用 %1 测试参数

  • 1

    这不仅是可能的,而且您希望的行为是批处理文件执行的正常行为,除非您执行某些操作'special':

    • 通过在资源管理器中双击批处理文件执行批处理文件时,cmd窗口将在完成时关闭;

    • 当从命令行执行批处理文件时,它只是在完成时返回到命令行提示符 - 窗口未关闭;

    所以我认为需要回答的问题是你在批处理文件中做了什么导致命令行在命令行执行时关闭?

  • 0

    使用 exit /b 0 ,而不是 exit

    如果从Windows资源管理器启动,前者将一直退出,但如果从命令行启动,则返回控制台 .

  • 2

    就像@anishsane一样,如果从资源管理器启动,我也想要一个暂停语句,但是从命令窗口启动时却不需要 .

    基于@ mousio上面的答案,这对我有用:

    @SET cmdcmdline|FINDSTR /b "cmdcmdline="|FINDSTR /i pushd >nul
    @IF ERRORLEVEL 1 (
        @echo.
        @echo Press ENTER when done
        @pause > nul
    )
    

    (这里没有任何原创,仅提供一个工作示例)

  • 13

    将其粘贴在BAT或CMD脚本的开头,并可能更改“if”子句中发生的情况:

    :: To leave command window open if script run from Windows explorer.
    @setlocal
    @set x=%cmdcmdline:"=%
    @set x=%x: =%
    @set y=%x:cmd/c=%
    @if "%x%" neq "%y%" cmd /k %0 %* && exit || exit
    @endlocal
    

    这样做,如果用户双击或使用“cmd / c”调用此脚本,它将使用“cmd / k”重新启动,这将在命令完成后使会话保持打开状态 . 这允许用户退出或者做其他事情 .

    这样做的原因而不是在这个答案中解释的其他方式是因为我发现情况仍然使用引号或其他符号,IF语句将在某些情况下调整QUOTES和/ c和有空格 . 所以逻辑首先删除所有QUOTES,然后删除所有空格..因为SOMETIMES删除引号后有一个额外的空格 .

    set x=%cmdcmdline:"=%       <-- removes all quotes
    set x=%x: =%                <-- removes all spaces
    set y=%x:cmd/c=%            <-- removes  cmd/c  from the string saving it to  y
    

    &&退出||的点exit是这样的,如果退出前的ERRORLEVEL为0(成功),则它会停止运行,但如果它不为0(某些失败),它也会停止运行 .

    但你可以替换这部分:

    cmd /k %0 %* && exit || exit
    

    有类似的东西

    set CALLED_WITH_CMD_C=YES
    

    然后在脚本的其余部分中弥补自己的差异 . 您必须移动或删除endlocal .

    前面的'@'符号可以防止回声,如果你想测试,你可以拥有回声 . 不要使用echo on或echo off,因为它会更改设置并影响调用您的所有后续脚本 .

  • 0

    @dlchambers很接近,但设置不起作用,因为cmdcmdline在某些情况下不是一个定义的环境变量,但这个版本基于他的作品对我很有用:

    echo %cmdcmdline% | findstr /i pushd >nul
    if errorlevel 1 pause
    
  • 0

    阅读完建议之后,这就是我的意思:

    set __cmdcmdline=%cmdcmdline%
    set __cmdcmdline=%__cmdcmdline:"=%
    set __cmdcmdline=%__cmdcmdline: =%
    set __cmdcmdline=%__cmdcmdline:~0,5%
    if "%__cmdcmdline%"=="cmd/c" set CMD_INITIATED_FROM_EXPLORER=1
    set __cmdcmdline=
    

    有条件地设置变量: CMD_INITIATED_FROM_EXPLORER

    ..随后可以根据需要使用:

    if defined CMD_INITIATED_FROM_EXPLORER (
      echo.
      pause
    )
    

    ..但是_968916提到的关于Powershell的问题没有解决:

    从Powershell运行./batch.cmd使用引擎盖下的cmd / c

相关问题