Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 将批处理文件延迟不到一秒钟?_Batch File - Fatal编程技术网

Batch file 将批处理文件延迟不到一秒钟?

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

是否有任何方法可以将批处理文件延迟不到一秒钟,例如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 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;
    }