tags:

views:

7667

answers:

11

When writing a batch file to automate something on a Windows box, I've needed to pause its execution for several seconds (usually in a test/wait loop, waiting for a process to start). At the time, the best solution I could find uses ping (I kid you not) to achieve the desired effect. I've found a better write-up of it here, which describes a callable "wait.bat", implemented as follows:

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

You can then include calls to wait.bat in your own batch file, passing in the number of seconds to sleep.

Apparently the Windows 2003 Resource Kit provides a Unix-like sleep command (at last!). In the meantime, for those of us still using XP, 2K or (sadly) NT, is there a better way?

Update

I've accepted ΤΖΩΤΖΙΟΥ's answer, as its the most lightweight and portable solution (the fact that Python is my language of choice may have influenced this decision :-). Many thanks to everyone who responded.

I modified his suggested sleep.py script, so that it defaults to 1 second if no arguments are passed on the command line:

import time, sys

time.sleep(float(sys.argv[1]) if len(sys.argv) > 1 else 1)
+3  A: 

The Resource Kit has always included this. At least since Windows 2000.

Also, the cygwin package has a sleep - plop that into your PATH and include the cygwin.dll (or whatever it's called) and way to go!

Daren Thomas
Note that cygwin1.dll does not peacefully coexist with different versions of itself. You better have one and only one cygwin1.dll on your machine, or you will get weird failures.
JesperE
+6  A: 

Sleep.exe is included in most DOS resource kits. If that is the case, that's the best idea.

If you don't have it, it's easily found on the Internet (I added it to my Windows XP). I assume of course that you can add executables to your box.

The windows 2003 resource kit. I guess Sleep should work regardless of your windows version

Luk
A: 

The Microsoft download page of the Windows 2003 Resource Kit indicates that it also works for XP. I'm afraid there is no other choice but to use an 'external' utility to do the waiting: there is nothing like this built into the XP command processor.

GerG
+3  A: 

I faced a similar problem, but just knocked up a very short C++ console app to do the same thing. Just run MySleep.exe 1000 - perhaps easier than downloading/installing the whole resource kit?

#include <tchar.h>
#include <stdio.h>
#include "Windows.h"

int _tmain(int argc, _TCHAR* argv[])
{
    if (argc == 2)
    {
     _tprintf(_T("Sleeping for %s ms\n"), argv[1]);
     Sleep(_tstoi(argv[1]));  
    }
    else
    {
     _tprintf(_T("Wrong number of arguements\n"));
    }

    return 0;
}
John Sibly
+2  A: 

The usage of ping is good, as long as you just want to "wait for a bit". This since you are dependant on other functions underneath, like your network working and the fact that there is nothing answering on 127.0.0.1. ;-) Maybe not very likely it fails, but not impossible...

If you want to be sure that you are waiting exactly the specified time, you should use the sleep functionality (which also have the advantage that it doesn't use CPU power or wait for a network to become ready) To find an already made executable for sleep is the most convenient way. Just drop it into your Windows folder or any other part of your standard path and it is always available.

Otherwise, if you have a compiling environment you can easily make one yourself. The Sleep function is available in kernel32.dll, so you just need to use that one. :-) For VB / VBA declare the following in the beginning of your source to declare a sleep function:

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

For C#:

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

More about his functionality (available since Windows 2000) you'll find here: http://msdn.microsoft.com/en-us/library/ms686298(VS.85).aspx

In standard C sleep() is included in the standard library and in Microsoft's Visual Studio C the function is named Sleep(), if memory serves me. ;-) Those two takes the argument in seconds, not in milliseconds as the two previous declarations.

Tooony
Sleep is available in the .net framework - have a look at the thread class, e.g.:using System.Threading;....Thread.Sleep(1000);
John Sibly
If "ping 127.0.0.1" fails, you have more serious stuff than "sleep" to worry about - this is the loopback interface, anything RPC will probably go mad.
Piskvor
+4  A: 

If you have Python installed, or don't mind installing it (it has other uses too :), just create the following sleep.py script and add it somewhere in your PATH:

import time, sys

time.sleep(float(sys.argv[1]))

It will allow sub-second pauses (e.g. 1.5 sec, 0.1 etc), should you have such a need. If you want to call it as sleep rather than sleep.py, then you can add the .PY extension to your PATHEXT environment variable. In XP, you can edit it in:

My Computer → Properties (menu) → Advanced (tab) → Environment Variables (button) → System variables (frame)

ΤΖΩΤΖΙΟΥ
+2  A: 

I have been using this C# sleep program. It might be more convenient for you if C# is your preferred language:

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");
            }
        }
    }
}
Liam
A: 

I faced the same problem in the past, and used ping myself (with a remark above clearly documenting that I realize this is stupid :) ).

Jack Leow
+1  A: 

Even more lightweight than the Python solution is a Perl one-liner.

To sleep for 7 seconds put this in the BAT script:

perl -e "sleep 7"

This solution only provides a resolution of 1 second.

If you need higher resolution then use the Time::HiRes module from CPAN. It provides usleep() which sleeps in microseconds and nanosleep() which sleeps in nanoseconds (both functions takes only integer arguments). See the StackOverflow question http://stackoverflow.com/questions/896904, "millisecond sleep in Perl" for further details.

I have used ActivePerl for many years. It is very easy to install and can be downloaded from http://downloads.activestate.com/ActivePerl/Windows/5.10/ (use the latest, build number 1005).

Peter Mortensen
+1  A: 

Over at serverfault, a similar question was asked, the solution there was:

choice /d y /t 5 > nul
mlsteeves
+1  A: 

You could use the Windows cscript WSH layer and this wait.js JavaScript file:

if (WScript.Arguments.Count() == 1)
    WScript.Sleep(WScript.Arguments(0)*1000);
else
    WScript.Echo("Usage: cscript wait.js seconds");
Blake7