シェル プロセスの終了日時を調べる
Visual Basic for Applications (VBA) プロシージャで Shell 関数を実行すると、実行可能プログラムが非同期的に開始され、プロシージャに制御が返されます。 このシェル プログラムは、終了されるまでユーザーのプロシージャとは関係なく実行を続けます。
プロシージャがシェル プロセスの終了を待機する必要がある場合、Windows API を使用してアプリケーションの状態をポーリングできますが、この方法はあまり効率的ではありません。 このトピックでは、より効率的な方法について説明します。
Windows API には、シェル プロセスが完了するまでアプリケーションが待機できるようにする機能が統合されています。 これらの機能を使用するには、シェル プロセスへのハンドルが必要です。 ハンドルを取得するには、Shell 関数の代わりに CreateProcess 関数を使用してシェル プログラムを開始する必要があります。
シェル化されたプロセスを作成する
アドレス指定できるプロセスを作成するには、CreateProcess 関数を使用してシェル アプリケーションを開始します。 CreateProcess 関数を使用すると、プログラムに渡されるパラメーターの 1 つを通じて、プログラムにシェル プロセスのプロセス ハンドルが提供されます。
シェル化されたプロセスが終了するまで待ちます
CreateProcess 関数を使ってプロセス ハンドルを取得した後で、そのハンドルを WaitForSingleObject 関数に渡すことができます。 これにより、VBA プロシージャはシェル プロセスが終了するまで実行を中断します。
次の手順は、 CreateProcess 関数を使用して Windows メモ帳アプリケーションを実行する VBA プロシージャを構築するために必要です。 このコードは、Windows API の CreateProcess 関数と WaitForSingleObject 関数を使用して、シェル プロセスの終了を待機してから実行を再開する方法を示します。
CreateProcess 関数の構文は複雑なため、このコード例では ExecCmd という名前の関数にカプセル化されています。 ExecCmd が受け取るパラメーターは、実行するアプリケーションのコマンド ラインです。
標準モジュールを作成し、次の行を宣言セクションに貼り付けます。
Option Explicit Private Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Private Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessID As Long dwThreadID As Long End Type Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _ hHandle As Long, ByVal dwMilliseconds As Long) As Long Private Declare Function CreateProcessA Lib "kernel32" (ByVal _ lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _ lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _ ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _ ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _ lpStartupInfo As STARTUPINFO, lpProcessInformation As _ PROCESS_INFORMATION) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal _ hObject As Long) As Long Private Const NORMAL_PRIORITY_CLASS = &H20& Private Const INFINITE = -1&
次のコードをモジュールに貼り付けます。
Public Sub ExecCmd(cmdline As String) Dim proc As PROCESS_INFORMATION Dim start As STARTUPINFO Dim ReturnValue As Integer ' Initialize the STARTUPINFO structure: start.cb = Len(start) ' Start the shelled application: ReturnValue = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _ NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc) ' Wait for the shelled application to finish: Do ReturnValue = WaitForSingleObject(proc.hProcess, 0) DoEvents Loop Until ReturnValue <> 258 ReturnValue = CloseHandle(proc.hProcess) End Sub
関数をテストするには、[ イミディエイト ] ウィンドウに次のコードを貼り付け、 Enter キーを押します。 メモ帳が起動します。 しばらくしてからメモ帳を閉じます。 メモ帳が閉じると、メッセージ ボックスが表示されます。
ExecCmd "NOTEPAD.EXE": MsgBox "Process Finished"
サポートとフィードバック
Office VBA またはこの説明書に関するご質問やフィードバックがありますか? サポートの受け方およびフィードバックをお寄せいただく方法のガイダンスについては、Office VBA のサポートおよびフィードバックを参照してください。