Определение времени окончания процесса в оболочке
При выполнении функции Оболочки в процедуре 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 принимает один параметр — командную строку выполняемого приложения.
Создайте стандартный модуль и вставьте следующие строки в раздел Объявления:
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
Чтобы протестировать функцию, вставьте следующий код в окно Интерпретация и нажмите клавишу ВВОД. Блокнот запускается. Через некоторое время закройте Блокнот. Окно сообщения появляется при закрытии Блокнота.
ExecCmd "NOTEPAD.EXE": MsgBox "Process Finished"
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.