Спать в пакетном файле - PullRequest
139 голосов
/ 03 октября 2008

При написании командного файла для автоматизации чего-либо на коробке Windows, мне нужно было приостановить его выполнение на несколько секунд (обычно в цикле тестирования / ожидания, ожидая запуска процесса). В то время лучшее решение, которое я мог найти, использует ping (я не шучу) для достижения желаемого эффекта. Я нашел лучшее описание этого здесь , которое описывает вызываемый "wait.bat", реализованный следующим образом:

@ping 127.0.0.1 -n 2 -w 1000 > nul
@ping 127.0.0.1 -n %1% -w 1000> nul

Затем вы можете включить вызовы wait.bat в свой собственный пакетный файл, передав количество секунд для сна.

Очевидно, Windows 2003 Resource Kit предоставляет Unix-подобную команду сна (наконец-то!). В то же время, для тех из нас, кто все еще использует Windows XP, Windows 2000 или (к сожалению) Windows NT , есть ли лучший способ?

Я изменил сценарий sleep.py в принятом ответе , так что по умолчанию он равен одной секунде, если в командной строке не передано никаких аргументов:

import time, sys

time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)

Ответы [ 30 ]

6 голосов
/ 03 июня 2014
timeout /t <seconds> <options>

Например, чтобы скрипт выполнял непрерывное 2-секундное ожидание:

timeout /t 2 /nobreak >NUL

Это означает, что сценарий будет ждать 2 секунды, прежде чем продолжить.

По умолчанию нажатие клавиши прерывает тайм-аут, поэтому используйте переключатель /nobreak, если вы не хотите, чтобы пользователь мог прервать (отменить) ожидание. Кроме того, тайм-аут будет предоставлять посекундные уведомления, чтобы уведомить пользователя, как долго еще ждать; это можно удалить, отправив команду на NUL.

edit: Как @ martineau указывает в комментариях , команда timeout доступна только в Windows 7 и выше. Кроме того, команда ping использует меньше процессорного времени, чем timeout. Я все еще верю в использование timeout везде, где это возможно, поскольку оно более читабельно, чем ping 'hack'. Подробнее здесь .

5 голосов
/ 25 марта 2011

Просто поместите это в свой пакетный файл, где вы хотите ждать.

@ping 127.0.0.1 -n 11 -w 1000 > null
5 голосов
/ 21 февраля 2014

Есть лучший способ спать, используя пинг. Вы захотите пропинговать адрес, который не существует, поэтому вы можете указать время ожидания с точностью до миллисекунды. К счастью, такой адрес определен в стандарте (RFC 3330), и это 192.0.2.x. Это не выдумка, это действительно адрес с единственной целью несуществования (это может быть непонятно, но это применимо даже в локальных сетях):

192.0.2.0 / 24 - этот блок назначен как "TEST-NET" для использования в документация и пример кода. Часто используется в сочетании с доменные имена example.com или example.net в поставщике и протоколе документация. Адреса в этом блоке не должны появляться на общедоступный интернет.

Чтобы спать в течение 123 миллисекунд, используйте ping 192.0.2.1 -n 1 -w 123 >nul

4 голосов
/ 03 октября 2008

Resource Kit всегда включал это. По крайней мере, начиная с Windows 2000.

Кроме того, в пакете Cygwin есть sleep - plop, который входит в вашу PATH и включает cygwin.dll (или как там это называется) и способ пойти!

4 голосов
/ 29 мая 2013

Если у вас есть PowerShell в вашей системе, вы можете просто выполнить эту команду:

powershell -command "Start-Sleep -s 1"

Редактировать: из мой ответ в похожей теме , люди поднимали вопрос, где время, которое требуется PowerShell для запуска, значительно по сравнению с тем, сколько времени вы пытаетесь ждать. Если важна точность времени ожидания (т. Е. Дополнительная задержка в одну или две секунды), вы можете использовать этот подход:

powershell -command "$sleepUntil = [DateTime]::Parse('%date% %time%').AddSeconds(5); $sleepDuration = $sleepUntil.Subtract((get-date)).TotalMilliseconds; start-sleep -m $sleepDuration"

Это занимает время, когда была введена команда windows, и сценарий powershell спит до 5 секунд после этого времени. Так что, пока PowerShell требует меньше времени для запуска, чем продолжительность сна, этот подход будет работать (на моей машине это около 600 мс).

4 голосов
/ 18 января 2013

В блокноте напишите:

@echo off
set /a WAITTIME=%1+1
PING 127.0.0.1 -n %WAITTIME% > nul
goto:eof

Теперь сохраните как wait.bat в папке C: \ WINDOWS \ System32, тогда всякий раз, когда вы хотите подождать, используйте:

CALL WAIT.bat <whole number of seconds without quotes>
3 голосов
/ 07 июля 2009

Я использовал эту программу сна C #. Возможно, вам будет удобнее, если вы предпочитаете C #:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace sleep
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                double time = Double.Parse(args[0]);
                Thread.Sleep((int)(time*1000));
            }
            else
            {
                Console.WriteLine("Usage: sleep <seconds>\nExample: sleep 10");
            }
        }
    }
}
3 голосов
/ 29 января 2013

Мне нравится Ответ Аасини . Я добавил его для обработки дня, а также разрешил ему обрабатывать центсекунды (%TIME% выходы H:MM:SS.CC):

:delay
SET DELAYINPUT=%1
SET /A DAYS=DELAYINPUT/8640000
SET /A DELAYINPUT=DELAYINPUT-(DAYS*864000)

::Get ending centisecond (10 milliseconds)
FOR /F "tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, ENDING=((H*60+M)*60+S)*100+X+DELAYINPUT
SET /A DAYS=DAYS+ENDING/8640000
SET /A ENDING=ENDING-(DAYS*864000)

::Wait for such a centisecond
:delay_wait
FOR /F "tokens=1-4 delims=:." %%A IN ("%TIME%") DO SET /A H=%%A, M=1%%B%%100, S=1%%C%%100, X=1%%D%%100, CURRENT=((H*60+M)*60+S)*100+X
IF DEFINED LASTCURRENT IF %CURRENT% LSS %LASTCURRENT% SET /A DAYS=DAYS-1
SET LASTCURRENT=%CURRENT%
IF %CURRENT% LSS %ENDING% GOTO delay_wait
IF %DAYS% GTR 0 GOTO delay_wait
GOTO :EOF
2 голосов
/ 03 октября 2008

Использование ping хорошо, если вы просто хотите «немного подождать». Это связано с тем, что вы зависите от других функций, таких как ваша сеть и тот факт, что на 127.0.0.1 ничего не отвечает. ;-) Может быть, это не очень вероятно, что это терпит неудачу, но это не невозможно ...

Если вы хотите быть уверены, что ожидаете точно указанное время, вы должны использовать функцию sleep (которая также имеет то преимущество, что она не использует питание процессора или ожидает готовности сети).

Найти уже готовый исполняемый файл для сна - самый удобный способ. Просто поместите его в папку Windows или любую другую часть стандартного пути, и он всегда будет доступен.

В противном случае, если у вас есть среда компиляции, вы можете легко создать ее самостоятельно. Функция Sleep доступна в kernel32.dll, поэтому вам просто нужно ее использовать. :-) Для VB / VBA объявите следующее в начале вашего источника, чтобы объявить функцию сна:

private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (byval dwMilliseconds as Long)

Для C #:

[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);

Подробнее об этой функции (доступно начиная с Windows 2000) вы можете узнать в Функция сна (MSDN).

В стандартном C sleep() входит в стандартную библиотеку, а в Microsoft Visual Studio C функция называется Sleep(), если мне не изменяет память. ;-) Эти два аргумента принимают аргументы в секундах, а не в миллисекундах, как два предыдущих объявления.

2 голосов
/ 05 февраля 2014

Лучшее решение, которое должно работать на всех версиях Windows после Windows 2000, будет:

timeout numbersofseconds /nobreak > nul
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...