[VB] Shell 関数で起動したプログラムの終了を待つ方法 | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

VB や VBA から外部のプログラムを実行する1つの方法として、Shell 関数を使用する方法があります。


ところが、この Shell 関数はプログラムを起動すると、その終了を待たずに次のステップへと処理を進めてしまいます。


プログラムの終了を待って次の処理に進みたい場合は、Win32API を利用して起動したプロセスの終了を待機しなければなりません。


そのためのサンプルコードを以下に示します。


Public Declare Function OpenProcess Lib &quotkernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function WaitForSingleObject Lib &quotkernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function CloseHandle Lib &quotkernel32" (ByVal hObject As Long) As Long
Public Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
Public Const INFINITE As Long = &HFFFF

Sub main()
    
    Dim procId As Long                                      'プロセスID
    Dim hProc As Variant                                    'プロセスハンドル
    
    procId = Shell("notepad.exe")                           '外部プログラムを起動します。

    hProc = OpenProcess(PROCESS_ALL_ACCESS, False, procId)  'プロセスハンドルを取得します。
    If hProc > 0 Then                                       'プロセスハンドルを取得できた場合
        Call WaitForSingleObject(hProc, INFINITE)           'プロセスがシグナル状態になるまで待ちます。
        CloseHandle hProc                                   'プロセスハンドルを解放します。
    End If
    MsgBox ("メモ帳の実行を終了しました。")

End Sub


このサンプルコードでは、Shell 関数を使用してメモ帳を起動した後、Win32API の OpenProcess 関数を呼び出して起動したメモ帳のプロセスハンドルを取得し、WaitForSingleObject 関数を呼び出してその終了を待ち、終了すると CloseHandle を使用してそのプロセスハンドルを解放し、次のステップ(メッセージボックスの表示)へと処理を進めています。


Win32API の宣言部や呼び出し部の詳細についてはあえて触れません。詳細についてはWin32APIのリファレンスなどを参照してください。

(私は”おまじない”だと思って記述しています。)