Batch file 将批处理文件延迟不到一秒钟?
是否有任何方法可以将批处理文件延迟不到一秒钟,例如10毫秒 我试着写下:Batch file 将批处理文件延迟不到一秒钟?,batch-file,Batch File,是否有任何方法可以将批处理文件延迟不到一秒钟,例如10毫秒 我试着写下: ping localhost -n 1 -w 10 但它不起作用 有人能帮忙吗 pathping 127.0.0.1 -n -q 1 -p 100 >nul 是关于以毫秒为单位的适当等待/延迟的讨论。根据上一篇文章,路径应该在毫秒内完成工作 使用mshta(这将等待500毫秒): 使用自编译.NET可执行文件的另一种方法: @if (@X)==(@Y) @end /* JScript comment @echo
ping localhost -n 1 -w 10
但它不起作用
有人能帮忙吗
pathping 127.0.0.1 -n -q 1 -p 100 >nul
是关于以毫秒为单位的适当等待/延迟的讨论。根据上一篇文章,路径应该在毫秒内完成工作
使用mshta(这将等待500毫秒):
使用自编译.NET可执行文件的另一种方法:
@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal
::del %~n0.exe /q /f
::
:: For precision better call this like
:: call waitMS 500
:: in order to skip compilation in case there's already built .exe
:: as without pointed extension first the .exe will be called due to the ordering in PATEXT variable
::
::
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
set "jsc=%%v"
)
if not exist "%~n0.exe" (
"%jsc%" /nologo /w:0 /out:"%~n0.exe" "%~dpsfnx0"
)
%~n0.exe %*
endlocal & exit /b %errorlevel%
*/
import System;
import System.Threading;
var arguments:String[] = Environment.GetCommandLineArgs();
function printHelp(){
Console.WriteLine(arguments[0]+" N");
Console.WriteLine(" N - milliseconds to wait");
Environment.Exit(0);
}
if(arguments.length<2){
printHelp();
}
try{
var wait:Int32=Int32.Parse(arguments[1]);
System.Threading.Thread.Sleep(wait);
}catch(err){
Console.WriteLine('Invalid Number passed');
Environment.Exit(1);
}
@if(@X)==(@Y)@end/*JScript注释
@回音
setlocal
::del%~n0.exe/q/f
::
::为了精确起见,最好这样称呼
::打500
::以便在已生成.exe的情况下跳过编译
::由于PATEXT变量的顺序,将首先调用.exe,因为没有指向的扩展名
::
::
对于/f“tokens=*delims=“%%v in('dir/b/s/a:-d/o:-n”%SystemRoot%\Microsoft.NET\Framework\*jsc.exe“)do(
设置“jsc=%%v”
)
如果不存在“%~n0.exe”(
%jsc%/nologo/w:0/out:“%~n0.exe”“%~dpsfnx0”
)
%~n0.exe%*
结束本地和退出/b%错误级别%
*/
进口制度;
导入系统。线程;
变量参数:String[]=Environment.GetCommandLineArgs();
函数printHelp(){
Console.WriteLine(参数[0]+“N”);
WriteLine(“等待N毫秒”);
环境。退出(0);
}
if(arguments.length一段时间前,它给出了从15毫秒开始的精确时间间隔。这是整个post的副本
我认为在延迟较小的情况下,我实现了毫秒级的延迟和精确的计时。我使用了一个混合的批处理JScript解决方案和WScript.Sleep方法,但是为了避免每次使用JScript部分时的加载延迟,这两个部分必须同时处于活动状态。JScript进程以毫秒为单位进行延迟,然后执行延迟和sen向批处理部分发送一个信号。批处理向JScript发送毫秒数并等待该信号。实现这种双向通信的方法是通过JScript的WshShwll.Exec方法,该方法可以访问批处理的Stdin和Stdout流
@if (@CodeSection == @Batch) @then
@echo off
setlocal EnableDelayedExpansion
if defined restart goto secondPart
rem First part: execute JScript section, so it re-execute this Batch file
set restart=true
CScript //nologo //E:JScript "%~F0" "%~F0"
goto :EOF
:secondPart
rem To do a delay, use: "echo #millisecs" followed by "set /P ="; use "echo 0" to end
rem To display data in the screen, use: echo data > CON
rem To read data from keyboard, use set /P "data=Prompt: " < CON > CON
set runs=10
For %%t in (5 10 15 20 30 50 100 250 500 1000) do (
set time_idle_ms=%%t
(
set t0=!time!
for /L %%p in (1,1,%runs%) do echo %%t& set /P =
set t1=!time!
)
for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
)
set /a average_time=a*10/runs
echo(Input:!time_idle_ms! ms - Output: Average time !average_time! ms > CON
)
rem Send the signal to end JScript section
echo 0
goto :EOF
@end
// JScript section
// Restart this Batch file with access to its Stdin and Stdout streams
var WshShell = new ActiveXObject("WScript.Shell");
var BatchFile = WshShell.Exec('"'+WScript.Arguments(0)+'"'), delay;
// Get delay, wait and send CR until delay equ 0
while ((delay = BatchFile.Stdout.ReadLine()) != "0" ) {
WScript.Sleep(delay);
BatchFile.Stdin.WriteLine();
}
Windows 8.1 32位-3.2 GHz中的另一项测试
Input:5 ms - Output: Average time 14 ms
Input:10 ms - Output: Average time 16 ms
Input:15 ms - Output: Average time 15 ms
Input:20 ms - Output: Average time 31 ms
Input:30 ms - Output: Average time 32 ms
Input:50 ms - Output: Average time 61 ms
Input:100 ms - Output: Average time 110 ms
Input:250 ms - Output: Average time 250 ms
Input:500 ms - Output: Average time 501 ms
Input:1000 ms - Output: Average time 1000 ms
编辑:路径
添加测试
为了完成本主题,我使用pathping
和用于测试我的方法的相同代码进行了计时测试。如下所示:
@echo off
setlocal EnableDelayedExpansion
set runs=10
For %%t in (5 10 15 20 30 50 100 250 500 1000) do (
set time_idle_ms=%%t
(
set t0=!time!
for /L %%p in (1,1,%runs%) do pathping 127.0.0.1 -n -q 1 -p %%t >nul
set t1=!time!
)
for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
)
set /a average_time=a*10/runs
echo(Input:!time_idle_ms! ms - Output: Average time !average_time! ms
)
结果表明,对于较小的延迟时间,pathfing
不可靠:
Input:5 ms - Output: Average time 48 ms
Input:10 ms - Output: Average time 47 ms
Input:15 ms - Output: Average time 47 ms
Input:20 ms - Output: Average time 62 ms
Input:30 ms - Output: Average time 63 ms
Input:50 ms - Output: Average time 93 ms
Input:100 ms - Output: Average time 141 ms
Input:250 ms - Output: Average time 281 ms
Input:500 ms - Output: Average time 532 ms
Input:1000 ms - Output: Average time 1031 ms
下面我有三种不同的纯脚本解决方案,用于在批处理脚本中提供次秒延迟。所有这些解决方案的最小延迟因机器而异。只要超过最小延迟,它们通常都精确到10毫秒以内
我使用了Aacini的测试工具来测试所有三种方法的准确性,因此结果可以直接与他的结果进行比较
批处理宏
这个纯批量解决方案在概念上非常简单。我得到当前时间(精度为1/100秒),添加延迟,然后在一个紧密的循环中等待新的时间
我已将此逻辑打包在一种高级批处理宏技术中,该技术很难理解和开发,但易于使用。通过使用宏,调用不会引入延迟。如果您想了解有关批处理宏理论的更多信息,以及如何编写自己的宏,请参阅和
此纯批量解决方案的最小延迟为三台机器中的最小延迟。在我测试的两台机器上,最小延迟范围为~15到~30毫秒。此宏仅支持小于24小时的延迟
此宏的主要缺点是它会消耗CPU资源—在整个延迟期间,将单个CPU机器与单个内核的使用率固定为100%
@echo off
setlocal disableDelayedExpansion
::******** Define the @delay macro ****************
:: define LF as a Line Feed (newline) character
set ^"LF=^
^" Above empty line is required - do not remove
:: define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
set @delay=for %%# in (1 2) do if %%#==2 (%\n%
for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, arg1/=10"%\n%
cmd /v:on /c for /l %%. in (^^^) do @for /f "tokens=1-4 delims=:.," %%a in ("^!time: =0^!"^^^) do @set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100,tDiff=t2-t1"^^^>nul^^^&(if ^^^^!tDiff^^^^! lss 0 set /a tDiff+=8640000^^^>nul^^^)^^^&if ^^^^!tDiff^^^^! geq ^^^^!arg1^^^^! exit%\n%
endlocal%\n%
) else setlocal enableDelayedExpansion^&set arg1=
::********** Demonstrate usage ********************
echo Delaying for 1.25 seconds ...
%@delay% 1250
echo done.
echo(
::*********** Testing accuracy ********************
setlocal enableDelayedExpansion
echo Testing accuracy:
set runs=10
for %%t in (10 20 30 40 50 70 100 250 500 1000) do (
(
set t0=!time!
for /l %%p in (1,1,%runs%) do %@delay% %%t
set t1=!time!
)
for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
)
set /a average_time=a*10/runs
echo(Input:%%t ms - Output: Average time !average_time! ms
)
--样本结果--
SLEEP.BAT-混合JScript/Batch(与语言环境无关)
这是我最喜欢的解决方案。我调用我的SLEEP.BAT实用程序,传入所需的延迟,加上调用时的当前%time%
。批处理脚本调用嵌入在同一文件中的JScript,该脚本从当前时间中减去调用时间,以确定已经经过了多少时间,然后从m计算脚本应睡眠多长时间的延迟时间。此解决方案使用WScript.sleep()方法,该方法是事件驱动的,不消耗CPU资源
如果批处理脚本未传入,它将提供自己的%time%
值,但由于调用该实用程序所需的时间较长,因此准确性可能会受到影响
CSCRIPT初始化需要相当长的时间,因此最小延迟比宏解决方案长。在我的两台机器上,最小延迟范围为~30到~55毫秒
SLEEP.BAT应该可以在任何Windows计算机上工作,无论您的区域设置如何显示日期和时间。我使用此实用程序的唯一问题是,如果在从标准时间转换为夏令时之前的瞬间调用,它可能会给出错误的延迟,反之亦然
SLEEP.BAT
@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment
@goto :batch
:::
:::SLEEP.BAT msec [%time%]
:::SLEEP.BAT /?
:::
::: Suspend processing for msec milliseconds. The optional %time% argument
::: can be added to improve timing accuracy. If called within a FOR loop,
::: then !time! should be used instead, after enabling delayed expansion.
:::
::: There is a startup time for SLEEP.BAT that limits the shortest delay
::: possible. The startup time varies from machine to machine. Delays longer
::: than the minimum are usually accurate to within 10 msec if the %time%
::: argument is provided. One exception is when SLEEP.BAT is called the
::: instant before changing from standard to daylight savings time, in which
::: case the delay is extended by the startup time. The other exception occurs
::: when changing from daylight savings to standard, in which case the delay
::: never exceeds the startup time.
:::
::: A single /? argument displays this help.
:::
::: SLEEP.BAT Version 1.0 - written by Dave Benham
:::
============= :Batch portion ===========
@echo off
if "%~1" equ "/?" (
for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do @echo(%%A
exit /b 0
) else cscript //E:JScript //nologo "%~f0" %* %time%
exit /b
============ JScript portion ==========*/
try {
var arg2 = WScript.Arguments.Item(1).split(/[:.,]/);
var start = new Date();
if (start.getHours()<Number(arg2[0])) start.setDate( start.getDate()-1 );
start.setHours( Number(arg2[0]),
Number(arg2[1]),
Number(arg2[2]),
Number(arg2[3])*10
);
var delay = Number(WScript.Arguments.Item(0));
var adjustedDelay = delay - ((new Date())-start);
if (adjustedDelay>0) WScript.sleep( (adjustedDelay>delay) ? delay : adjustedDelay );
WScript.Quit(0);
} catch(e) {
WScript.Stderr.WriteLine("SLEEP.BAT - Invalid call");
WScript.Quit(1);
}
--样本输出--
LocaleSleep.bat-混合JScript/Batch(依赖于区域设置)
这与SLEEP.BAT几乎相同,只是它传入的是%date%%time%”
而不是%time%
。优点是它不再存在标准时间和夏令时之间转换的问题。主要缺点是它依赖于区域设置。只有当日期对象parse()正确解析了%date%
时,它才起作用方法。我知道这应该适用于大多数美国机器以及其他一些机器。可以编写变体以支持其他区域设置,但每个变体都依赖于区域设置
LocaleSleep.bat
@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment
@goto :batch
:::
:::LocaleSleep.bat msec ["%date% %time%"]
:::LocaleSleep.bat /?
:::
::: Suspend processing for msec milliseconds. The optional "%date% %time%"
::: argument can be added to improve timing accuracy. If called within a
::: FOR loop, then "!date! !time!" should be used instead, after enabling
::: delayed expansion.
:::
::: This utility is locale specific. It only works properly if %date% is in
::: a format that is parsed properly by the Date object parse() method.
:::
::: There is a startup time for SLEEP.BAT that limits the shortest delay
::: possible. The startup time varies from machine to machine. Delays longer
::: than the minimum are usually accurate to within 10 msec if the
::: "%date% %time%" argument is provided.
:::
::: A single /? argument displays this help.
:::
::: LocaleSleep.bat Version 1.0 - written by Dave Benham
:::
============= :Batch portion ===========
@echo off
if "%~1" equ "/?" (
for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do @echo(%%A
exit /b 0
) else cscript //E:JScript //nologo "%~f0" %* "%date% %time%"
exit /b
============ JScript portion ==========*/
try {
var arg2 = WScript.Arguments.Item(1);
var delay = Number(WScript.Arguments.Item(0)) - ((new Date())-(new Date(arg2.slice(0,-3))).setMilliseconds( Number(arg2.slice(-2))*10 ));
if (delay>0) WScript.sleep(delay);
WScript.Quit(0);
} catch(e) {
WScript.Stderr.WriteLine("localeSleep.bat - Invalid call");
WScript.Quit(1);
}
测试线束和使用演示
@echo off
setlocal enableDelayedExpansion
set runs=10
for %%t in (20 30 40 50 70 100 250 500 1000) do (
(
set t0=!time!
for /l %%p in (1,1,%runs%) do call sleep %%t !time!
set t1=!time!
)
for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
)
set /a average_time=a*10/runs
echo(Input:%%t ms - Output: Average time !average_time! ms
)
@echo off
setlocal enableDelayedExpansion
set runs=10
for %%t in (20 30 40 50 70 100 250 500 1000) do (
(
set t0=!time!
for /l %%p in (1,1,%runs%) do call localeSleep %%t "!date! !time!"
set t1=!time!
)
for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
)
set /a average_time=a*10/runs
echo(Input:%%t ms - Output: Average time !average_time! ms
)
结果与SLEEP几乎相同。BAT的SLEEP.exe部分可以指定睡眠时间(以毫秒为单位):
start "" /wait /min /realtime mshta "javascript:setTimeout(function(){close();},500)"
λ sleep /?
Usage: sleep time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)
路径127.0.0.1-n-Q1-P100>nul
我建议改为使用localhost
,路径选择localhost-n-q
@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment
@goto :batch
:::
:::LocaleSleep.bat msec ["%date% %time%"]
:::LocaleSleep.bat /?
:::
::: Suspend processing for msec milliseconds. The optional "%date% %time%"
::: argument can be added to improve timing accuracy. If called within a
::: FOR loop, then "!date! !time!" should be used instead, after enabling
::: delayed expansion.
:::
::: This utility is locale specific. It only works properly if %date% is in
::: a format that is parsed properly by the Date object parse() method.
:::
::: There is a startup time for SLEEP.BAT that limits the shortest delay
::: possible. The startup time varies from machine to machine. Delays longer
::: than the minimum are usually accurate to within 10 msec if the
::: "%date% %time%" argument is provided.
:::
::: A single /? argument displays this help.
:::
::: LocaleSleep.bat Version 1.0 - written by Dave Benham
:::
============= :Batch portion ===========
@echo off
if "%~1" equ "/?" (
for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do @echo(%%A
exit /b 0
) else cscript //E:JScript //nologo "%~f0" %* "%date% %time%"
exit /b
============ JScript portion ==========*/
try {
var arg2 = WScript.Arguments.Item(1);
var delay = Number(WScript.Arguments.Item(0)) - ((new Date())-(new Date(arg2.slice(0,-3))).setMilliseconds( Number(arg2.slice(-2))*10 ));
if (delay>0) WScript.sleep(delay);
WScript.Quit(0);
} catch(e) {
WScript.Stderr.WriteLine("localeSleep.bat - Invalid call");
WScript.Quit(1);
}
@echo off
setlocal enableDelayedExpansion
set runs=10
for %%t in (20 30 40 50 70 100 250 500 1000) do (
(
set t0=!time!
for /l %%p in (1,1,%runs%) do call localeSleep %%t "!date! !time!"
set t1=!time!
)
for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
)
set /a average_time=a*10/runs
echo(Input:%%t ms - Output: Average time !average_time! ms
)
λ sleep /?
Usage: sleep time-to-sleep-in-seconds
sleep [-m] time-to-sleep-in-milliseconds
sleep [-c] commited-memory ratio (1%-100%)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <Windows.h>
int main(int argc, char* argv[])
{
int n = atoi(argv[1]);
Sleep(n);
return 0;
}