Shell関数は非同期、WshShellは同期と非同期

VBAで他のアプリケーションの起動を行う場合はShell関数を利用するのがラクですが、Shell関数は常に非同期で起動するため、同期起動をしたい場合には利用できません。

同期起動を行いたい場合にはVBAのShell関数とWin32APIのWaitForSingleObject関数を組み合わせて利用する方法や、WScript(Windows Script Host)のWshShellクラスを利用する方法があります。

どちらでやっても同期処理は可能なのですが、Win32APIを利用する場合はWaitForSingleObject関数以外にもウィンドウハンドルの概念やOpenProcess関数やCloseHandle関数なども利用しなければならず、結構手間が掛かりますしコード量も増えます。ただし、処理待ちのタイムアウト判定など細かい設定が出来る利点もあります。

ここではそこまで手間が掛からないWshShellクラスを利用する方法を紹介します。

VBAのShell関数の使い方は「VBAで他のアプリケーションを起動する(Shell)」で紹介しています。


参照設定

WshShellはCreateObject関数を利用してこのような書き方を紹介されることが多いと思います。

しかしこの書き方では利用できるプロパティやメソッドを候補表示できません。しかし参照設定を行えばプロパティやメソッドを表示することが可能です。

WshShellの参照設定は、VBA画面→ツールメニュー→参照設定で「Windows Script Host Object Model」を選択します。これでWshShellクラスを利用できるようになります。

以下はWshShellクラスのインスタンス変数の作成サンプルです。書き方は2通りあります。どちらでもいいです。1つ目のように1行で書いてもいいですし、2つ目のように変数定義とSetを別に書いてもいいです。厳密には分けた方がいいのですがほとんど影響がありません。気になる方は「VBAでクラス変数の宣言とNewを1行で書いてよいか」をご参照ください。

以降のサンプルコードは参照設定を行った場合の書き方になります。


Runメソッドの構文

WshShellクラスには複数のプロパティとメソッドが用意されていますが、他アプリケーションの起動はRunメソッドを利用するだけで実現できます。

ここではRunメソッドの構文を紹介します。

WshShell Runオブジェクトを利用する場合はWshShellクラスのインスタンス変数のメソッドとして利用する必要があります。
Command 実行する他アプリケーションを文字列(ダブルクォーテーションで囲った形)で指定します。環境変数に対応しているため、%windir%のような書き方や環境変数PATHに定義されているアプリケーションであればアプリケーション名だけでの指定が可能です。アプリケーションに引数の指定が必要な場合はアプリケーション名の後ろを半角スペースで区切り記述します。
WindowStyle 表示するウィンドウの形式を指定します。省略時の既定値は1です。

内容
0 タスクバーには表示されません。そのためウィンドウもありません。完全に非表示状態で起動します。この状態で起動した場合は通常はタスクマネージャから終了させることになります。
1 既定値です。直前に起動したときのウィンドウサイズで起動します。タスクバーにも表示されます。選択された状態で表示されます。ヘルプでは初回表示時はこの値を使うことを指定されています(が、他の値を使っても問題はないように見えます)。
2 最小化された状態で起動します。選択状態になります。
3 最大化された状態で起動します。選択状態になります。
4 直前に起動したときのウィンドウサイズで起動しますが、選択された状態にはなりません。
5 直前に起動したときのウィンドウサイズで起動します。タスクバーにも表示されます。選択された状態で表示されます。起動に関しては1と同じ挙動です。
6 最小化された状態で起動します。選択された状態にはなりませんがOSが持つウィンドウの表示順では現在アクティブになっているウィンドウの次の位置になります。
7 最小化された状態で起動します。選択された状態にはなりません。
8 直前に起動したときのウィンドウサイズで起動します。選択された状態にはなりません。
9 起動に関しては1と同じ挙動です。ヘルプでは最小化されたウィンドウ復元時にはこの値を使うことを指定されています。
10 アプリケーションの起動時の状態に依存します。
WaitOnReturn 起動したアプリケーションの終了を待つかどうかを指定します。Trueはアプリケーションが終了するのを待ちますが、Falseは待たずに次の処理に移行します。省略時の既定値はFalseです。
Long(戻り値) 正常に起動すると0を返します。異常時は何も返しません。エラー判定には利用できません。



サンプルコード

以下のサンプルは開きたいファイルを指定してメモ帳を起動して、閉じるまで待つコードです。メモ帳が閉じられるまでRunメソッド以降のコードは実行されず待機状態になります。

実行結果

指定したtestfile.txtをメモ帳で開き、そのメモ帳が閉じられるまで待ちます。

5行目のようにフルパスで書いてもいいですし、6行目のように環境変数(%windir%など)を指定して書いてもパスを展開して解釈してくれます。


Runメソッドエラー時

Runメソッドで起動に失敗した場合は実行時エラーが発生します。主にアプリケーションのパスが間違っている場合に発生します。