記事公開日
最終更新日
並列処理の話(その2) Windowsでコマンドを並列実行する(後編)

(本記事の情報は、記事の公開日時点での情報であり、その正確性、完全性、最新性等内容を保証するものではありません。)
前回は、STARTコマンドでコンソールコマンドを並列動作させる方法を解説しました。
並列処理の話(その2) Windowsでコマンドを並列実行する(前編)
今回は、複数並列動作させたコマンドの終了待ちをする方法を解説します。
起動されたコマンドは、Windows内でプロセスという単位で実行されています。プロセスが動作中かどうかを判断するためには、プロセスIDが必要です。しかし、STARTコマンドは起動したプロセスのプロセスIDを返してくれません。
そこで、Windowsに標準装備されている「WMI:Windows Management Instrumentation」という機能を使用します。WMIを制御するコマンドは「wmic」です。
起動してみましょう。
(Win32_Process)->Create() を実行しています
メソッドが正しく実行しました。
出力パラメーター
instance of __PARAMETERS
{
ProcessId = 1780;
ReturnValue = 0;
};
- treeコマンドはEXEではなくCOMなので、「tree」だけでは動きません。
- 「tree.com c:」をひとかたまりのパラメータとしてwmicに認識させるため、ダブルクォートで括ってやります。
正常に起動された場合、ProccessIdが表示され、ReturnValueは0になります。
次に、このProcessIdが稼働中かどうかチェックします。
利用できるインスタンスがありません。
うっかりしている間にコマンドが終わってしまったようです。
今度はtree実行中に急いでコマンドを打ちます。
(Win32_Process)->Create() を実行しています
メソッドが正しく実行しました。
出力パラメーター
instance of __PARAMETERS
{
ProcessId = 12868;
ReturnValue = 0;
};
C:Usersosuga>wmic process where (PROCESSID=12868) GET Caption
Caption
tree.com
- 「GET Caption」がないと、いろんな情報がたくさん出て来てしまうので、Caotion(コマンド名)だけを表示するようにします。
Captionというカラムにtree.comというコマンド名が表示されました。どうやら、Captionという文字列が表示されればプロセスは生きていると考えて良さそうです。
この実験の結果から、バッチを作成してみましょう。
それでは、新しいバッチファイルを作成し、次の文を入力してください。

コピー用テキストはこちら
FOR /F "TOKENS=1,2 DELIMS==; " %%I IN ('WMIC PROCESS CALL CREATE "tree.com c:\"') DO (
if "%%I" EQU "ProcessId" set ProcessId=%%J
if "%%I" EQU "ReturnValue" set ReturnValue=%%J
)
echo %ProcessId%
echo %RetuenValue%
if %ReturnValue% neq 0 goto :Error
echo Process Execute OK PID=%ProcessId%
:LOOP
set NOWEXEC=OFF
FOR /F "TOKENS=1 DELIMS= " %%I IN ('WMIC PROCESS WHERE ^(PROCESSID^=%ProcessId%^) GET CAPTION') DO (
if "%%I" EQU "Caption" set NOWEXEC=ON
)
if "%NOWEXEC%" EQU "ON" goto :LOOP
:DONE
echo Process %ProcessId% is done.
goto :EOF
:Error
echo Proces start error.
実行すると、tree.comが終了するまでうまく待ってくれているようです。
しかし、この方法では、複数のプロセスを待てないので、もう一ひねりして、複数のプロセスを待つようにします。

コピー用テキストはこちら
FOR /F "TOKENS=1,2 DELIMS==; " %%I IN ('WMIC PROCESS CALL CREATE "tree.com c:\"') DO (
if "%%I" EQU "ProcessId" set ProcessId1=%%J
if "%%I" EQU "ReturnValue" set ReturnValue1=%%J
)
echo %ProcessId1%
echo %RetuenValue1%
if %ReturnValue1% neq 0 goto :Error
FOR /F "TOKENS=1,2 DELIMS==; " %%I IN ('WMIC PROCESS CALL CREATE "tree.com c:\"') DO (
if "%%I" EQU "ProcessId" set ProcessId2=%%J
if "%%I" EQU "ReturnValue" set ReturnValue2=%%J
)
echo %ProcessId2%
echo %RetuenValue2%
if %ReturnValue1% neq 0 goto :Error
echo Process Execute OK PID=%ProcessId1%,%ProcessId2%
:LOOP
set NOWEXEC=OFF
FOR /F "TOKENS=1 DELIMS= " %%I IN ('WMIC PROCESS GET PROCESSID') DO (
if "%%I" EQU "%ProcessId1%" set NOWEXEC=ON
if "%%I" EQU "%ProcessId2%" set NOWEXEC=ON
)
if "%NOWEXEC%" EQU "ON" goto :LOOP
:DONE
echo Process %ProcessId1%,%ProcessId2% is done.
goto :EOF
:Error
echo Proces start error.
プロセスの存在チェックでプロセスIDだけを表示し、合致するものがある間はループを続けるようにしました。(この場合、DELIMSは必要ないですね)
一つ目と二つ目のプロセスが直書きで、ちょっとダサいですが、実行できることはわかっていただけると思います。
この方法の唯一の問題点は、実行コマンドの終了コードが取得できないということです。
さて、ちょっとオマケなのですが、このWMICというコマンド。
パラメーターに「/NODE:”192.168.10.1”」というように別のマシンのIPアドレスかマシン名を入れると、リモートでのプロセス実行と終了監視ができます。実行ユーザーの権限などまだ考慮することはありますが、Unixのrshellのような事ができるので、試してみたらいかがでしょうか。
関連コンテンツ
並列処理の話(その1) ~変換処理の並行動作について(前編)~
並列処理の話(その1) ~変換処理の並行動作について(後編)~
並列処理の話(その2) Windowsでコマンドを並列実行する(前編)
並列処理の話(その4) ハイパースレッディング・テクノロジー
追記:Waha! Transformer 製品サイトの関連コンテンツ
データの抽出や加工、連携にお悩みではありませんか?
20年以上の実績に裏打ちされた信頼のデータ連携ツール「Waha! Transformer」で、自社に眠るデータを有効活用。まずは無料のハンズオンセミナーや体験版で効果を実感していただけます。