シェル プロセスの終了日時を調べる

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 が受け取るパラメーターは、実行するアプリケーションのコマンド ラインです。

  1. 標準モジュールを作成し、次の行を宣言セクションに貼り付けます。

    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& 
    
    
  2. 次のコードをモジュールに貼り付けます。

    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
    
  3. 関数をテストするには、[ イミディエイト ] ウィンドウに次のコードを貼り付け、 Enter キーを押します。 メモ帳が起動します。 しばらくしてからメモ帳を閉じます。 メモ帳が閉じると、メッセージ ボックスが表示されます。

    ExecCmd "NOTEPAD.EXE": MsgBox "Process Finished" 
    

サポートとフィードバック

Office VBA またはこの説明書に関するご質問やフィードバックがありますか? サポートの受け方およびフィードバックをお寄せいただく方法のガイダンスについては、Office VBA のサポートおよびフィードバックを参照してください。