エンジョイ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 対 VMware Player対決

先日、バーチャルマシン上でプログラムをビルドすると時間がかかってしようがない。ビルドするならやっぱネイティブマシンだよね、と話している人がいました。 その人が使っているのはホスト型の仮想化だったのです …

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

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

Cygwin上でiperfをビルド

ネットワークの疎通確認に便利なツールiperf。 先日Windows上で使おうと思ったら、見つからなくて困ったことがありました。 iperfのWindows版バイナリも配布されているらしいですが、私は …

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

前回の続きです。 作成した仮想マシンにUbuntu 14.04のサーバー版をインストールするところまで。スクリーンショットでどうぞ。 なぜかこのときキーボードの自動検出に失敗したんですよね…。 しよう …

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

ついにリリースされました、Ubuntu 14.04。 実験用にインストールした13.10はともかく、実用に使っていた12.04マシンの調子が最近悪くて。インストールし直したかったけど、あと少しで14. …