如何在批处理/cmd中让程序休眠五秒钟

872

Windows的截图工具可以捕捉屏幕,但有时候我想在五秒后捕捉屏幕,比如拍摄通过网络摄像头显示的图像(例如运行脚本并对着摄像头微笑)。

我如何在批处理文件中等待五秒钟?


27
针对来到这里的人的快速回答:自Windows Vista起,有一种本地解决方案:TIMEOUT。参考文献:SS64Rob van der Woude - Gras Double
3
有一个名为“timeout”的命令,可以等待若干秒。如果需要毫秒级别的睡眠,可以使用PowerShell的“Start-Sleep”命令。在CMD中休眠50毫秒的方法是:powershell Start-Sleep -m 50 - Pavel P
@Pavel:你也可以滥用ping命令来让程序休眠数毫秒。 - Joey
12
尝试这个:timeout /t 5 /nobreak >nul。它会等待5秒钟,然后静默结束,不会有任何输出。 - user9556248
如果你安装了Node.js,可以使用node -e 'setTimeout(a => a, 5000)'来玩一下。它适用于Mac上的Node v12.14.0,可能在Windows上也适用。 - nonopolarity
显示剩余2条评论
30个回答

19

两种答案:

首先,在批处理文件中延迟执行,无需使用人们一直在提出的繁琐方法:

timeout /t <TimeoutInSeconds> [/nobreak] 

http://technet.microsoft.com/zh-cn/library/cc754891.aspx

其次,值得一提的是,虽然它可能不能完全符合您的要求,但使用内置的 Windows 截图工具,您可以在不使用鼠标的情况下触发截图。运行截图工具,在当前截图中退出但保留工具运行,并在需要截图时按 Control + Print Screen。这不应该干扰您正在尝试截图的任何内容。


16
我试图在msbuild任务中实现此操作,但由于I/O重定向,choice和timeout都无法正常工作。
最终我使用了来自http://sourceforge.net/projects/unxutils的sleep.exe,这很好因为它不需要任何安装并且体积很小。
尝试使用choice:
<Target Name="TestCmd">
  <Exec Command="choice /C YN /D Y /t 5 " />
</Target>

结果显示:

TestCmd:
  choice /C YN /D Y /t 5

EXEC : error : The file is either empty or does not contain the valid choices. [test.proj]
  [Y,N]?
C:\test.proj(5,9): error MSB3073: The command "choice /C YN /D Y /t 5 " exited with code 255.

尝试使用timeout
<Target Name="TestCmd">
  <Exec Command="timeout /t 5 " />
</Target>

结果为:

TestCmd:
  timeout /t 5
EXEC : error : Input redirection is not supported, exiting the process immediately. [test.proj]
C:\test.proj(5,7): error MSB3073: The command "timeout /t 5 " exited with code 1.

附言:

我实际上正在使用 <Exec Command="sleep 2 & dbghost.exe" />,因为我要同时执行多个dbghost.exe程序,它们会根据当前秒数创建临时文件/数据库 - 这意味着如果您启动多个实例,则每个实例都使用相同的临时名称。最初我尝试使用MSBuild Extension Pack的Thread.Sleep命令,但似乎(通常)它能够正常运行睡眠任务,但然后在所有线程中同时开始<exec>任务,当然dbghost.exe会因冲突而失败。到目前为止,使用sleep.exe似乎更可靠。


4
关于在msbuild任务中选择/超时不起作用的非常有帮助的注释。在这种情况下,我发现接受的答案(ping)对我在msbuild中也有效:ping 1.1.1.1 -n 1 -w 3000 > nul - Steve Cadwallader
同时,在 Ant 任务中,choice/timeout 也无法正常工作。 - DonBecker
1
针对构建服务器!在非交互式进程/帐户下,CHOICETIMEOUT无法工作。在构建机器上忘记它们。如果您的网络连接失败,则PING 1.1.1.1无法工作。在这里寻找W32TMTypePerf和一些PowerShell。或者创建您自己的.NET可执行文件。 - it3xl

13

还有两种方法适用于从XP及以上的所有系统:

使用 w32tm 命令:

w32tm /stripchart /computer:localhost /period:5 /dataonly /samples:2  1>nul 

使用 typeperf 命令:

typeperf "\System\Processor Queue Length" -si 5 -sc 1 >nul

使用mshta(不需要设置网络):

start "" /w /b /min mshta "javascript:setTimeout(function(){close();},5000);"

1
这些已经测试过了!当网络连接中断时,您的 TypePerfTYPEPERF 命令可以正常工作。 - it3xl

9
这是我实际使用的最新版本,用于在脚本完成后暂停十秒以查看输出。
BEST>@echo done
BEST>@set DelayInSeconds=10
BEST>@rem Use ping to wait
BEST>@ping 192.0.2.0 -n 1 -w %DelayInSeconds%000 > nul

echo done语句可以让我看到脚本何时结束,并且ping命令提供了延迟时间。额外的 @ 符号意味着我可以看到 “done” 文本,而等待过程不会分散我的注意力。

我已经在XP机器上尝试了这里给出的各种解决方案,因为想要一个可以在多种机器上运行的批处理文件,所以我选择了XP机器作为环境,因为它很可能是最不具备能力的环境。

GOOD> ping 192.0.2.0 -n 1 -w 3000 > nul

按预期,这似乎会产生三秒的延迟。一次ping尝试持续指定的3秒钟。

BAD> ping -n 5 192.0.2.0 > nul

这需要约10秒钟(而不是5秒)。我的解释是有5个ping尝试,每个尝试大约间隔1秒,共计4秒。每个ping尝试可能持续大约1秒钟,总计估计耗时9秒钟。

BAD> timeout 5
BAD> sleep /w2000
BAD> waitfor /T 180
BAD> choice

命令不可用。

BAD> ping 192.0.2.0 -n 1 -w 10000 > nul :: wait 10000 milliseconds, ie 10 secs

我也尝试过上面的方法,通过使用两个连续的冒号可以在BAT文件中添加注释。然而,软件几乎立即返回。将注释放在ping命令之前单独一行就可以正常工作。

GOOD> :: wait 10000 milliseconds, ie 10 secs
GOOD> ping 192.0.2.0 -n 1 -w 10000 > nul

为了更好地理解ping的实际作用,我运行了以下命令:
ping 192.0.2.0 -n 5 -w 5000

这个测试大约需要30秒,即使5*5=25。我的解释是,有5个ping尝试,每个持续5秒,但在ping尝试之间有大约1秒的时间延迟:毕竟,如果您立即重新ping并且它最好给网络一点时间从任何问题中恢复过来,不要期望有不同的结果。
编辑:从另一个帖子(链接)中窃取,.. RFC 3330表示IP地址192.0.2.0不应出现在互联网上,因此ping此地址可防止这些测试向任何人发送垃圾邮件! 我已相应地修改了上面的文本!

1
关于cmd批处理文件中的注释:注释应该以REM命令开头。请参见https://dev59.com/M3A75IYBdhLWcg3w_ef1#2997627。双冒号实际上是一个被命令处理器忽略的误用标签。如果在自己的行上使用,它将作为注释工作,但要注意:如果在IF语句内部使用,它将破坏执行流程。 - Wim
1
使用ping命令有两种方法:1.对现有地址(127.0.0.1)或不存在的地址(192.0.2.0)进行ping。现有地址将在不到一毫秒的时间内回复,因此您需要对其进行n+1次ping以获得n秒的延迟。不存在的地址将超时,因此您需要将超时值设置为n*1000以获得n秒的延迟。 - Wim

6
我做了这个东西。它能够运行并显示剩余时间(以秒为单位)。如果你想使用它,请将它添加到批处理文件中:

call wait 10

我测试时它是可以工作的。 wait.bat清单(它必须放在工作目录或windir/system32/中):
@echo off

set SW=00

set SW2=00

set /a Sec=%1-1

set il=00
@echo Wait %1 second
for /f "tokens=1,2,3,4 delims=:," %%A in ("%TIME%") do set /a HH=%%A, MM=1%%B-100, SS=1%%C-100, CC=1%%D-100, TBASE=((HH*60+MM)*60+SS)*100+CC, SW=CC 

set /a TFIN=%TBASE%+%100

:ESPERAR
for /f "tokens=1,2,3,4 delims=:," %%A in ("%TIME%") do set /a HH=%%A, MM=1%%B-100, SS=1%%C-100, 

CC=1%%D-100, TACTUAL=((HH*60+MM)*60+SS)*100+CC,  SW2=CC


if %SW2% neq %SW% goto notype
if %il%==0 (echo Left %Sec% second & set /a Sec=sec-1 & set /a il=il+1)
goto no0
:notype
set /a il=0
:no0

if %TACTUAL% lss %TBASE% set /a TACTUAL=%TBASE%+%TACTUAL%
if %TACTUAL% lss %TFIN% goto ESPERAR

5

你可以使用 VBScript,例如文件myscript.vbs

set wsobject = wscript.createobject("wscript.shell")

do while 1=1
    wsobject.run "SnippingTool.exe",0,TRUE
    wscript.sleep 3000
loop

批处理文件:
cscript myscript.vbs %1

3
为什么是%1?你的代码中没有为参数留出任何位置。我使用这段代码:sleep.vbs:wscript.sleep wscript.arguments(1) - Jeremy

5

这是用户Aacini提出的代码改进版,它的时间精度可以达到百分之一秒,并且在时间达到23:59:59.99时不会出现错误:

for /f "tokens=1,2,3,4 delims=:," %%A in ("%TIME%") do set /a HH=%%A, MM=1%%B-100, SS=1%%C-100, CC=1%%D-100, TBASE=((HH*60+MM)*60+SS)*100+CC

:: Example delay 1 seg.
set /a TFIN=%TBASE%+100

:ESPERAR
for /f "tokens=1,2,3,4 delims=:," %%A in ("%TIME%") do set /a HH=%%A, MM=1%%B-100, SS=1%%C-100, CC=1%%D-100, TACTUAL=((HH*60+MM)*60+SS)*100+CC

if %TACTUAL% lss %TBASE% set /a TACTUAL=%TBASE%+%TACTUAL%
if %TACTUAL% lss %TFIN% goto ESPERAR

4

我使用完全基于Windows XP功能的以下方法在批处理文件中进行延迟:

文件 DELAY.BAT

@ECHO OFF
REM DELAY seconds

REM GET ENDING SECOND
FOR /F "TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100,     S=1%%C%%100, ENDING=(H*60+M)*60+S+%1

REM WAIT FOR SUCH A SECOND
:WAIT
FOR /F "TOKENS=1-3 DELIMS=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, CURRENT=(H*60+M)*60+S
IF %CURRENT% LSS %ENDING% GOTO WAIT

您还可以在计算中插入日期,这样当延迟间隔跨越午夜时,该方法也能正常工作。

10
这是一种“忙等待”的方法,可能会对您的机器性能造成不良影响。在运行时,请查看任务管理器以了解对CPU使用率的影响。 - yoyo

4
我最简单的方法是这样的:
下载Sleep.exe,网址为http://www.sleepcmd.com/。.exe文件应该和你编写的程序在同一个文件夹中!

10
如果下载.exe文件是正确的答案,那么从微软资源工具包中获取sleep.exe会是一个更好的选择。并将它放在路径中。 - Jeremy

4

通过批处理文件中的两行简单代码就可以实现:在%temp%文件夹中编写一个临时的.vbs文件并调用它:

echo WScript.Sleep(5000) >"%temp%\sleep.vbs"
cscript "%temp%\sleep.vbs"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接