エンジョイAsobi

スマホとWindowsとLinuxを遊ぶ。

Windows

Windowsバッチファイルの処理を一時停止させる sleep コマンド

投稿日:2014年3月17日 更新日:

先日Windowsのバッチファイルを使っていて、不便だなと感じたことがありました。

ある実験をしていて、Windows PCから自動的に繰り返し繰り返し操作を加えていたのですが、ある操作と操作の間にポーズを挟む必要が生じました。しかもそのポーズ時間をミリ秒単位で変動させる必要がありました。

実験の自動化に普段はTeraTermマクロやらシェルスクリプト、expectやら駆使するのですが、そのときはどうしてもWindowsのバッチファイルしか使えない事情があって。

何年もWindowsを使っていながらそこで初めて気づいたのですが、Windows(Windows7)のバッチファイルでは、ミリ秒単位のポーズを挟む方法が標準では用意されていないのですね。

その時は時間も無かったので、急遽Windows Resource Kit Toolsを入手してその中に含まれるsleepコマンドを使いましたが、とっってもまどろっこしい思いをしました。

先日そんなことがあって、この週末はプライベートに少し余裕があったので、パパッと作ってみましたよ。お手製の Sleepコマンド!

パパッと作ったと言っても、Windowsの開発環境すら持っていなくて、Visual Studio Express 2013をインストールするところから始めたので、トータルの時間はかかりましたけどね。Visual Studio Express 2013インストール記は、また時間がとれたら書こうと思います。

ソースを公開しても、稚拙なコードで恥ずかしい以外の問題はたぶん無いと思うので、公開します。

お手製 sleepコマンドのバイナリはこちら
Visual Studio Express 2013 の Solutionファイルはこちら

バイナリの利用には
http://www.visualstudio.com/ja-jp/downloads/download-visual-studio-vs
から Visual C++ Redistributable for Visual Studio 2013のx86版をインストールする必要があります。

Cygwin入れるとか代替手段はいくらもありますが、もし同じことで困っている方がいらっしゃればお使いください。ただし万一損害が生じても一切責任はとれないのでご了承ください。また再配布はしないでください。

またCopyrightに関して一つ。sleep作るにあたって、Free Getoptというオープンソースソフトウェアを利用させていただきました。作者に感謝いたします。再配布条件にある各表示は、バイナリについてはアーカイブに同梱、ソースについてはソースファイルのヘッダーに表示してあります。

しかしこれも今回初めて気づいたのですが、Windowsの開発環境には getopt()が無い!?のですかね。これはもしかしたら私の探し方が悪いのかもしれませんが。不便だなーと思いました。

#include <iostream>
#include <windows.h>
#include "stdafx.h"
#include "getopt.h"

using namespace std;

#define MAX_SEC            4000000
#define MAX_MSEC        4000000000

/*
 *    Usage
 */
static void
usage(void)
{
    cout
        << "Usage : sleep [-m] DURATION" << endl
        << "  Sleep in specified seconds, "
        << "or milliseconds if '-m' option was specified." << endl;
}

/*
 *    コマンドライン引数の読み込み
 */
static int
parse_arg(int argc, char *argv[], unsigned long *dur)
{
    int opt;
    unsigned long msec = 0, sec = 0, max = MAX_SEC;
    unsigned long *psec = &sec;
    char *ep;

    /*
     *    オプション引数のparse
     */
    while ((opt = getopt(argc, argv, "m")) != -1) {
        switch (opt) {
        //milliseconds指定
        case 'm':
            psec = &msec;
            max = MAX_MSEC;
            break;

        //不正なオプションがあった
        case '?':
            return -1;

        default:
            break;
        }
    }

    /*
     *    DURATION引数のparse
     */
    if (optind >= argc) {
        cerr << "DURATION is required." << endl;
        return -1;
    }
    *psec = strtoul(argv[optind], &ep, 10);
    if (*ep != '\0') {
        cerr << "Invalid argument." << endl;
        return -1;
    }
    if (*psec == ULONG_MAX || *psec > max) {
        cerr << "DURATION must be less than " << dec << max << "." << endl;
        return -1;
    }
    *dur = sec * 1000 + msec;

    return 0;
}

/*
 *    メイン
 */
int
main(int argc, char *argv[])
{
    unsigned long dur = 0;

    if (argc == 1) {
        usage();
        return 0;
    }

    if (parse_arg(argc, argv, &dur) < 0)
        return -1;

    Sleep(dur);

    return 0;
}

-Windows

関連記事

Hyper-Vの動的メモリは本当に動的だった!?

前回、無用なトラブルを避けるつもりで無難な選択をした結果、却ってロクでもない目に遭ったようだという話を書きました。 Hyper-V + Ubuntuなんてメジャーな組み合わせでは、そんなこと気にせずと …

Windows 8.1上でHyper-Vを試す ~ネットワークがつながらない~

前回、Hyper-V上の仮想マシンにUbuntuをインストールしたところまで書きました。 インストールが完了して、さっそく仮想マシンにSSHからログインしてあれこれ設定しようとしました。しかし、 SS …

metaWeblog.newMediaObject メソッドへの応答が無効です

ブログの執筆にWindows Live Writerを使っています。 この記事を投稿しようとしたら、 「ブログサーバーから受信した metaWeblog.newMediaObject メソッドへの応答 …

Windows 8.1上でHyper-Vを試す ~Ubuntuの仮想マシンを作る(1)~

Linuxのカーネルソースをあれこれいじるにあたって、実験用のLinux環境が欲しくなり、新たにUbuntuの仮想マシンを作ることにしました。 で仮想化ソフトに何使うか考えたのですが、自宅ではWind …

Hyper-VでUbuntu 14.04を試す(3)

前回、仮想マシンにUbuntu 14.04をインストールしました。 続いて環境整備。 まずはIPアドレスをDHCPから固定アドレスに変更。うちの宅内LANではSSHしたりリモートデスクトップしたりする …