教えて!ExcelVBA!

ExcelVBAの基礎知識・書き方について紹介します。

【ExcelVBA API操作】アプリケーション終了までプログラム実行を待機(GetExitCodeProcess)する方法を教えて!

f:id:m_kbou:20210521060213p:plain

アプリケーションのプロセス終了状態を返すWindowsAPI関数(GetExitCodeProcess)について紹介します。GetExitCodeProcessを使用する事で対象のアプリケーションが終了するまでプログラム実行を待機させる事も可能です。

 

 

構文

記述方法は以下の通りとなります。

(API定義)

Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long

----------------------------------------

(定数)

Public Const 処理終了値 = &H103&

----------------------------------------

(VBA記述)

GetExitCodeProcess(hProcess, lpExitCode)

[説明]:

アプリケーションのプロセス終了状態を返すAPI関数はGetExitCodeProcess関数となります。VBAから呼び出して使用する場合には、

---------------------------------

・定義

Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long

・定数

Public Const 処理終了値 = &H103&

---------------------------------

をプロシージャ外で宣言します。

引数であるhProcessにはプロセスハンドル値を指定し、lpExitCodeには終了コードを取得する変数を指定します。GetExitCodeProcess関数を実行すると戻り値として「0」又は「0以外」が返ります。「0」の場合はプロセス終了のステータス取得に失敗した状態となり、「0以外」の場合は成功した状態となります。

 

使い方

使用方法について説明します。 

[プログラミング例]:

'*------------------------------------------
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

Public Const アクセス方法 = &H1F0FFF

'*------------------------------------------
Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long

Public Const 処理終了値 = &H103&

'*------------------------------------------
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'*------------------------------------------

Sub アプリケーション終了までプログラム実行を待機する()

  '↓処理①
  Dim 戻り値 As Long
  Dim プロセス As Long
  Dim 終了コード As Long

  '↓処理②
  戻り値 = Shell("Notepad.exe", vbNormalFocus)

  '↓処理③
  プロセス = OpenProcess(アクセス方法, True, 戻り値)
  If (IsNull(プロセス) = True) Then
    MsgBox "取得に失敗しました。(ハンドル値:" & プロセス & ")"
    Exit Sub
  Else
    MsgBox "取得に成功しました。(ハンドル値:" & プロセス & ")"
  End If

  '↓処理④
  Do
    戻り値 = GetExitCodeProcess(プロセス, 終了コード)
    If (戻り値 = 0) Then
      MsgBox "終了ステータス取得エラー"
      GoTo 終了
    Else
      If (終了コード = 0) Then
        MsgBox "メモ帳を閉じました。"
      Else
        MsgBox "メモ帳は起動中です。"
        DoEvents
      End If
    End If
  Loop While (終了コード = 処理終了値)

終了:

  '↓処理⑤
  戻り値 = CloseHandle(プロセス)
  If (戻り値 = 0) Then
    MsgBox "解放に失敗しました。(戻り値:" & 戻り値 & ")"
  Else
    MsgBox "解放に成功しました。(戻り値:" & 戻り値 & ")"
  End If

End Sub

処理の流れは以下の通りとなります。

[処理①]:変数定義
戻り値・プロセス値・終了コードを格納する変数定義となります。

[処理②]:Shell関数によるメモ帳の起動
Shell関数を使用してメモ帳を起動します。起動時の戻り値(プロセスID)は[処理①]で定義した変数:戻り値にセットします。

[処理③]:OpenProcessによるプロセスハンドルの取得
※OpenProcessによるプロセスハンドルの取得についてはこちらを参照して下さい。

[処理④]:GetExitCodeProcessによるプロセス終了状態の取得
WindowsAPI関数であるGetExitCodeProcessを使用したプロセスの終了状態を取得します。各引数には以下の内容をセットして処理を実行します。
・hProcess・・・プロセスハンドル値を指定します。
     ※今回はOpenProcessで取得したプロセスハンドル値をセットします。
・lpExitCode・・・終了コードを取得する変数を指定します。
     ※今回は[処理①]で定義した変数:終了コードを指定します。
実行すると戻り値として「0」又は「0以外」が返されます。「0」の場合はプロセス終了のステータス取得に失敗した状態となり、「0以外」の場合は成功した状態となります。また、「0以外」の場合はプロセスの終了ステータスが変数:終了コードにセットされます。プロセスの終了ステータスは「0」又は「0以外」が戻り値となり、「0」の場合はプロセスが終了した事を意味し、「0以外」は起動中である事を意味します。起動中の場合はDoEventsにてWindowsへ制御を返し、プログラムの実行を待機させます。変数:終了コードと定数で記述した「処理終了値」が一致するまでプロセス終了状態をDo~Loop文にて繰り返し確認し、一致した場合には確認処理を終了します。

[処理⑤]:CloseHandleによるプロセスハンドルの解放
※OpenProcessによるプロセスハンドルの解放についてはこちらを参照して下さい。

f:id:m_kbou:20210521140325p:plain

※上記のプログラミング例は、VBE(VBA記述画面)に記述しないと実行ができません。VBEの開き方についてはこちらを参考にして下さい。

[実行例]:

①<実行>ボタンをクリックします。<実行>ボタンには上記のプログラミング例のプログラムが登録されています。(※ボタンの作り方やボタンにプログラムを割り当てるにはこちらを参考にして下さい。)

f:id:m_kbou:20210521060333p:plain

②メモ帳が開きます。

f:id:m_kbou:20210521060351p:plain

③メモ帳をアイコン化(最小化)します。

f:id:m_kbou:20210521060406p:plain

④メモ帳のプロセスハンドル値を取得する事ができたので、「取得に成功しました。(ハンドル値:4108)」がMsgBoxで表示されます。<OK>ボタンをクリックします。(※ハンドル値は状況により値が変わります。)

f:id:m_kbou:20210521060421p:plain

⑤「メモ帳は起動中です。」がMsgBoxで表示されます。<OK>ボタンをクリックすると再度「メモ帳は起動中です。」がMsgBoxで表示されます。(※これはメモ帳が起動中であるため、メモ帳が閉じられるまでループ処理で継続表示されます。)

f:id:m_kbou:20210521060445p:plain

⑥メモ帳を閉じます。

f:id:m_kbou:20210521060459p:plain

⑦「メモ帳を閉じました。」がMsgBoxで表示されます。<OK>ボタンをクリックします。

f:id:m_kbou:20210521060514p:plain

⑧メモ帳のプロセスハンドル値を解放する事ができたので、「解放に成功しました。(戻り値:1)」がMsgBoxで表示されます。<OK>ボタンをクリックします。

f:id:m_kbou:20210521060531p:plain

[サンプル]:

上記で説明したファイルをダウンロードできます。ご自由にお使い下さい。

drive.google.com

アプリケーション終了までプログラム実行を待機する方法についての説明は以上です。

 

おわりに

今回はWindowsAPI関数によるアプリケーション終了までプログラム実行を待機する方法について説明しました。是非参考にして下さい。