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関数を利用してこのような書き方を紹介されることが多いと思います。
1 2 |
Dim obj Set obj = CreateObject("WScript.Shell") |
しかしこの書き方では利用できるプロパティやメソッドを候補表示できません。しかし参照設定を行えばプロパティやメソッドを表示することが可能です。
WshShellの参照設定は、VBA画面→ツールメニュー→参照設定で「Windows Script Host Object Model」を選択します。これでWshShellクラスを利用できるようになります。
以下はWshShellクラスのインスタンス変数の作成サンプルです。書き方は2通りあります。どちらでもいいです。1つ目のように1行で書いてもいいですし、2つ目のように変数定義とSetを別に書いてもいいです。厳密には分けた方がいいのですがほとんど影響がありません。気になる方は「VBAでクラス変数の宣言とNewを1行で書いてよいか」をご参照ください。
1 |
Dim obj As New IWshRuntimeLibrary.WshShell |
1 2 |
Dim obj As IWshRuntimeLibrary.WshShell Set obj = New IWshRuntimeLibrary.WshShell |
以降のサンプルコードは参照設定を行った場合の書き方になります。
Runメソッドの構文
WshShellクラスには複数のプロパティとメソッドが用意されていますが、他アプリケーションの起動はRunメソッドを利用するだけで実現できます。
ここではRunメソッドの構文を紹介します。
1 |
Function WshShell.Run(Command As String, [WindowStyle], [WaitOnReturn As Boolean]) As Long |
WshShell | Runオブジェクトを利用する場合はWshShellクラスのインスタンス変数のメソッドとして利用する必要があります。 | ||||||||||||||||||||||||
Command | 実行する他アプリケーションを文字列(ダブルクォーテーションで囲った形)で指定します。環境変数に対応しているため、%windir%のような書き方や環境変数PATHに定義されているアプリケーションであればアプリケーション名だけでの指定が可能です。アプリケーションに引数の指定が必要な場合はアプリケーション名の後ろを半角スペースで区切り記述します。 | ||||||||||||||||||||||||
WindowStyle | 表示するウィンドウの形式を指定します。省略時の既定値は1です。
|
||||||||||||||||||||||||
WaitOnReturn | 起動したアプリケーションの終了を待つかどうかを指定します。Trueはアプリケーションが終了するのを待ちますが、Falseは待たずに次の処理に移行します。省略時の既定値はFalseです。 | ||||||||||||||||||||||||
Long(戻り値) | 正常に起動すると0を返します。異常時は何も返しません。エラー判定には利用できません。 |
サンプルコード
以下のサンプルは開きたいファイルを指定してメモ帳を起動して、閉じるまで待つコードです。メモ帳が閉じられるまでRunメソッド以降のコードは実行されず待機状態になります。
1 2 3 4 5 6 7 |
Sub WcriptShellRefer2() Dim obj As New IWshRuntimeLibrary.WshShell Dim ret As Long ' ret = obj.Run("C:\Windows\System32\notepad.exe ""C:\web\testfile.txt""", 1, True) ret = obj.Run("%windir%\System32\notepad.exe ""C:\web\testfile.txt""", 1, True) End Sub |
実行結果
指定したtestfile.txtをメモ帳で開き、そのメモ帳が閉じられるまで待ちます。
5行目のようにフルパスで書いてもいいですし、6行目のように環境変数(%windir%など)を指定して書いてもパスを展開して解釈してくれます。
Runメソッドエラー時
Runメソッドで起動に失敗した場合は実行時エラーが発生します。主にアプリケーションのパスが間違っている場合に発生します。