Получить этот хэндл можно двумя способами:
- С помощью функции Shell
Эта функция, запустив указанный exe, возвращает не хэндл, а идентификатор (ID) процесса. Разница между ними существенна: ID - всего лишь номер, тогда как с хэндлом связана различная нужная информация (к примеру, список того, чего конкретно вам разрешается делать с процессом - разрешается ли вам читать его память, завершать его и т.п.). Для получения хэндла из ID используется функция OpenProcess, которой передаётся ID процесса, а также желаемые права доступа. Нам нужно только одно - дождаться окончания, поэтому запрашиваем лишь право SYNCHRONIZE, указав соответствующую константу.
Например, для запуска Блокнота следует следует использовать (объявив предварительно константу SYNCHRONIZE, разумеется):- Код: Выделить всё
Dim hProcess As Long
hProcess = OpenProcess(SYNCHRONIZE, 0, Shell("notepad.exe", vbNormalFocus))
После того, как ожидание завершено, полученный хэндл нужно будет закрыть функцией CloseHandle (потому что больше он нам ни для чего не нужен).- Код: Выделить всё
Option Explicit
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Const SYNCHRONIZE As Long = &H100000
Private Const INFINITE As Long = &HFFFFFFFF
Private Sub Form_Load()
Dim hProcess As Long
hProcess = OpenProcess(SYNCHRONIZE, 0, Shell("notepad.exe", vbNormalFocus))
WaitForSingleObject hProcess, INFINITE
MsgBox "Вы закрыли Блокнот!", vbInformation
CloseHandle hProcess
End Sub
Константа INFINITE, передаваемая в WaitForSingleObject, означает, что мы готовы ждать завершения процесса, сколько потребуется, а не лишь определённое время. - Запустив процесс функцией CreateProcess
Функция Shell создаёт как бы "чужой" процесс: она внутри себя получает, но не передаёт нам хэндлы к созданному процессу, закрывая их - а это готовые хэндлы с правом полного доступа. Теоретически возможно (хотя и практически невероятно, настолько, что можно пренебречь), что система откажет в праве открыть процесс по ID с правом SYNCHRONIZE. Поэтому для полноты рассмотрим другой вариант запуска процесса с получением хэндлов, уже гарантированный:- Код: Выделить всё
Option Explicit
Private Declare Function WaitForSingleObject Lib "kernel32.dll" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByRef lpProcessAttributes As Any, ByRef lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByRef lpEnvironment As Any, ByVal lpCurrentDriectory As String, ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As PROCESS_INFORMATION) As Long
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Private Type STARTUPINFO
cb As Long
lpReserved As Long
lpDesktop As Long
lpTitle As Long
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 Byte
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Const STARTF_USESHOWWINDOW As Long = &H1
Private Const SW_NORMAL As Long = 1
Private Const NORMAL_PRIORITY_CLASS As Long = &H20
Private Const INFINITE As Long = &HFFFFFFFF
Private Sub Form_Load()
Dim si As STARTUPINFO, pi As PROCESS_INFORMATION
si.cb = Len(si)
si.dwFlags = STARTF_USESHOWWINDOW
si.wShowWindow = SW_NORMAL
'Хэндлы процесса и к потока будут позвращены в структуре pi, последний параметр.
CreateProcess vbNullString, "notepad.exe", ByVal 0&, ByVal 0&, 0, NORMAL_PRIORITY_CLASS, ByVal 0&, vbNullString, si, pi
'Нам не нужен хэндл потока, закроем его сразу.
CloseHandle pi.hThread
'А хэндл процесса - нужен, будем его ждать.
WaitForSingleObject pi.hProcess, INFINITE
MsgBox "Вы закрыли Блокнот!", vbInformation
CloseHandle pi.hProcess
End Sub
Нетрудно заметить, что во время ожидания завершения ваше приложение "висит" (и среда разработки тоже висит, если вы запускаете пример из неё). Иногда это именно то, что вам нужно, а иногда нет. Если вы хотите продолжать взаимодействие с пользователем, пока ждёте завершения какого-то процесса, вам понадобится контрол, расположенный здесь. Ему следует передать тот самый хэндл, два варианта получения которого показаны выше, всё остальное он сделает сам. Когда ожидание завершится, контрол сгенерирует событие Complete, которое и нужно обработать в коде. Пример по использованию контрола прилагается к нему в том же топике.
Для удобного копирования в будущем в код объявлений API-функций рекомендуется скачать API-Viewer, ссылка на который лежит тут.