先日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; }