Определение времени окончания процесса в оболочке

При выполнении функции Оболочки в процедуре Visual Basic для приложений (VBA) она запускает исполняемую программу асинхронно и возвращает управление процедуре. Эта оболочка программы продолжает выполняться независимо от процедуры, пока вы не закроете ее.

Если вашей процедуре нужно дождаться завершения оболочки, можно использовать API Windows для опроса состояния приложения, но это не очень эффективно. В этом разделе объясняется более эффективный метод.

Api Windows имеет интегрированные функции, которые позволяют приложению ждать завершения оболочки процесса. Чтобы использовать эти функции, необходимо иметь дескриптор для оболочки процесса. Для этого используйте функцию CreateProcess вместо функции Shell для запуска оболочки программы.

Создание оболочки процесса

Чтобы создать адресируемый процесс, используйте функцию CreateProcess для запуска оболочки приложения. Функция CreateProcess предоставляет программе дескриптор процесса оболочки с помощью одного из переданных параметров.

Дождитесь завершения оболочки процесса

После использования функции CreateProcess для получения дескриптора процесса можно передать этот дескриптор функции WaitForSingleObject . Это приводит к приостановке выполнения процедуры VBA до завершения оболочки процесса.

Следующие действия необходимы для создания процедуры VBA, которая использует функцию CreateProcess для запуска приложения Windows Notepad. В этом коде показано, как использовать функции CreateProcess и WaitForSingleObject в Windows API для ожидания завершения оболочки процесса перед возобновлением выполнения.

Синтаксис функции 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. Чтобы протестировать функцию, вставьте следующий код в окно Интерпретация и нажмите клавишу ВВОД. Блокнот запускается. Через некоторое время закройте Блокнот. Окно сообщения появляется при закрытии Блокнота.

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

Поддержка и обратная связь

Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.