windows 双击时暂停批处理文件而不是从控制台窗口运行时暂停?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3551888/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:05:46  来源:igfitidea点击:

Pausing a batch file when double-clicked but not when run from a console window?

windowsbatch-file

提问by Ben Blank

Is there a way for a batch file (in this case, running on Windows XP) to determine whether it was launched from a command line (i.e. inside a console window) or launched via the shell (e.g. by double-clicking)?

有没有办法让批处理文件(在这种情况下,在 Windows XP 上运行)确定它是从命令行启动(即在控制台窗口内)还是通过外壳启动(例如通过双击)?

I have a script which I'd like to have pause at certain points when run via the shell, but not when run at a command line. I've seen a similar questionon SO, but am unable to use the same solution for two reasons: first, whether or not it pauses needs to be dependent on multiple factors, only one of which is whether it was double-clicked. Second, I'll be distributing this script to others on my team and I can't realistically ask all of them to make registry changes which will affect all scripts.

我有一个脚本,我希望在通过 shell 运行时在某些点暂停,但在命令行上运行时不暂停。我在 SO 上看到了一个类似的问题,但是由于两个原因我无法使用相同的解决方案:首先,它是否暂停需要取决于多个因素,其中一个是它是否被双击。其次,我将把这个脚本分发给我团队中的其他人,我不能现实地要求他们所有人进行会影响所有脚本的注册表更改。

Is this possible?

这可能吗?

回答by Joey

Found one :-) – After desperately thinking of what cmdmight do when run interactively but not when launching a batch file directly ... I finally found one.

找到一个 :-) – 在拼命思考cmd交互运行时可​​能会做什么之后,而不是直接启动批处理文件时......我终于找到了一个。

The pseudo-variable %cmdcmdline%contains the command line that was used to launch cmd. In case cmdwas started normally this contains something akin to the following:

伪变量%cmdcmdline%包含用于启动cmd. 如果cmd正常启动,它包含类似于以下内容的内容:

"C:\Windows\System32\cmd.exe"

However, when launching a batch file it looks like this:

但是,当启动批处理文件时,它看起来像这样:

cmd /c ""C:\Users\Me\test.cmd" "

Small demo:

小演示:

@echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1
if defined DOUBLECLICKED pause

This way of checking might not be the most robust, though, but /cshould only be present as an argument if a batch file was launched directly.

不过,这种检查方式可能不是最可靠的,但/c仅当直接启动批处理文件时才应作为参数出现。

Works on my machine

在我的机器上工作

Tested here on Windows 7 x64. It may or may not work, break, do something weird, eat children (might be a good thing) or bite you in the nose.

在 Windows 7 x64 上进行了测试。它可能会也可能不会起作用,打破,做一些奇怪的事情,吃孩子(可能是一件好事)或咬你的鼻子。

回答by DocOc

A consolidated answer, derived from much of the information found on this page (and some other stack overflow pages with similar questions). This one does not rely on detecting /c, but actually checks for the name of the script in the command line. As a result this solution will not pause if you double-clicked on another batch and then called this one; you had to double-click on this particular batch file.

一个综合的答案,来自这个页面上的大部分信息(以及其他一些具有类似问题的堆栈溢出页面)。这个不依赖检测/c,而是在命令行中实际检查脚本的名称。因此,如果您双击另一个批次然后调用此解决方案,则该解决方案不会暂停;你必须双击这个特定的批处理文件。

:pauseIfDoubleClicked
setlocal enabledelayedexpansion
set testl=%cmdcmdline:"=%
set testr=!testl:%~nx0=!
if not "%testl%" == "%testr%" pause
  1. The variable "testl" gets the full line of the cmd processor call, stripping out all of the pesky double quotes.
  2. The variable "testr" takes "testl" and further strips outs the name of the current batch file name if present (which it will be if the batch file was invoked with a double-click).
  3. The if statement sees if "testl" and "testr" are different. If yes, batch was double-clicked, so pause; if no, batch was typed in on command line (or called from another batch file), go on.
  1. 变量“testl”获取 cmd 处理器调用的完整行,去掉所有讨厌的双引号。
  2. 变量“testr”采用“testl”并进一步删除当前批处理文件的名称(如果存在)(如果双击调用批处理文件,它将是)。
  3. if 语句查看“testl”和“testr”是否不同。如果是,批处理被双击,所以暂停;如果不是,批处理是在命令行中输入的(或从另一个批处理文件调用),继续。


Edit: The same can be done in a single line:

编辑:同样可以在一行中完成:

echo %cmdcmdline% | findstr /i /c:"%~nx0" && set standalone=1

In plain English, this

用简单的英语,这

  • pipes the value of %cmdcmdline%to findstr, which then searches for the current script name
  • %0contains the current script name, of course only if shifthas not been called beforehand
  • %~nx0extracts file name and extension from %0
  • >NUL 2>&1mutes findstrby redirecting any output to NUL
  • findstrsets a non-zero errorlevel if it can't find the substring in question
  • &&only executes if the preceding command returned without error
  • as a consequence, standalonewill not be defined if the script was started from the command line
  • 将 的值通过管道%cmdcmdline%传递给findstr,然后查找当前脚本名称
  • %0包含当前脚本名称,当然前提是shift没有被预先调用
  • %~nx0从中提取文件名和扩展名 %0
  • >NUL 2>&1通过将任何输出重定向到 NUL 来静音findstr
  • 如果 findstr找不到相关子字符串,则它会设置一个非零错误级别
  • &&仅当前面的命令没有错误返回时才执行
  • 因此,standalone如果脚本是从命令行启动的,则不会被定义

Later in the script we can do:

稍后在脚本中我们可以执行以下操作:

if defined standalone pause

回答by x0n

One approach might be to create an autoexec.nt file in the root of c:\ that looks something like:

一种方法可能是在 c:\ 的根目录中创建一个 autoexec.nt 文件,如下所示:

@set nested=%nested%Z

In your batch file, check if %nested% is "Z" - if it is "Z" then you've been double-clicked, so pause. If it's not "Z" - its going to be "ZZ" or "ZZZ" etc as CMD inherits the environment block of the parent process.

在您的批处理文件中,检查 %nested% 是否为“Z” - 如果是“Z”,则您已被双击,因此请暂停。如果它不是“Z”——它将是“ZZ”或“ZZZ”等,因为 CMD 继承了父进程的环境块。

-Oisin

-Oisin

回答by Kevin Fegan

A little more information...

多一点信息...

I start with a batch-file (test.cmd) that contains:

我从一个包含以下内容的批处理文件 (test.cmd) 开始:

@echo %cmdcmdline%

If I double-click the "test.cmd" batch-file from within Windows Explorer, the display of echo %cmdcmdline% is:

如果我在 Windows 资源管理器中双击“test.cmd”批处理文件, echo %cmdcmdline% 的显示是:

cmd /c ""D:\Path\test.cmd" "

When executing the "test.cmd" batch-file from within a Command Prompt window, the display of
echo %cmdcmdline% depends on how the command window was started...

从命令提示符窗口中执行“test.cmd”批处理文件时,
echo %cmdcmdline%的显示取决于命令窗口的启动方式...

If I start "cmd.exe" by clicking the "Start-Orb" and "Command Prompt" or if I click "Start-Orb" and execute "cmd.exe" from the search/run box. Then I execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is:

如果我通过单击“Start-Orb”和“命令提示符”启动“cmd.exe”,或者如果我单击“Start-Orb”并从搜索/运行框中执行“cmd.exe”。然后我执行“test.cmd”批处理文件,echo %cmdcmdline% 的显示是:

"C:\Windows\system32\cmd.exe"

Also, for me, if I click "Command Prompt" from the desktop shortcut, then execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is also:

另外,对我来说,如果我从桌面快捷方式中单击“命令提示符”,然后执行“test.cmd”批处理文件,则 echo %cmdcmdline% 的显示也是:

"C:\Windows\system32\cmd.exe"

But, if I "Right-Click" inside a Windows Explorer window and select "Open Command Prompt Here", then execute the "test.cmd" batch-file, the display of echo %cmdcmdline% is:

但是,如果我在 Windows 资源管理器窗口中“右键单击”并选择“在此处打开命令提示符”,然后执行“test.cmd”批处理文件,则 echo %cmdcmdline% 的显示为:

"C:\Windows\System32\cmd.exe" /k ver

So, just be careful, if you start "cmd.exe" from a shortcut that contains a "/c" in the "Target" field (unlikely), then the test in the previous example will fail to test this case properly.

因此,请注意,如果您从“目标”字段中包含“/c”的快捷方式启动“cmd.exe”(不太可能),那么上一个示例中的测试将无法正确测试这种情况。