To invoke an executable program from VB you can use Shell() function, but this function starts an executable program asynchronously and returns control to the procedure which called the function. The shelled program continues to run independently of your procedure until you close it.
There is an efficient but a bit complex way to make your procedure to wait until the shelled program ends. In this method you need to find out the process handle for the process shelled. Shell function won't return process handle, so to invoke the process you have to use 'CreateProcess' API instead. This CreateProcess will return process handle, using this handle 'WaitForSingleObject' is to be called to make the application to wait.
To test this code create a new project, insert a new form, draw a command button there and then paste the following code in 'general' section of the code window.
'Type declarations
to pass to CreateProcess API
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
'Declare the
API functions
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&
Private Const
SW_SHOWMINIMIZED = 2
Private Const
STARTF_USESHOWWINDOW = &H1
Private Const
SW_HIDE = 0
Private Const WAIT_ABANDONED = &H80
Private Const WAIT_OBJECT_0 = &H0
Private Const WAIT_TIMEOUT = &H102
'Create a procedure
to execute the command
Public Sub
ExecCmd(Cmdline As String)
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim ReturnValue As Integer
Dim lTimeOut As Long
' Initialize the STARTUPINFO structure:
start.cb = Len(start)
start.dwFlags = STARTF_USESHOWWINDOW
start.wShowWindow = SW_HIDE
' Start the shelled application:
ReturnValue = CreateProcessA(0&, Cmdline$, 0&, 0&, 1&,
NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
' Set time out in milliseconds
lTimeOut = 1000
' Wait for the shelled application to finish:
Do
ReturnValue = WaitForSingleObject(proc.hProcess, lTimeOut)
DoEvents
Loop Until ReturnValue <> WAIT_TIMEOUT
' Close the process handle
ReturnValue = CloseHandle(proc.hProcess)
End Sub
Sub Command1_Click()
ExecCmd "CALC.EXE"
MsgBox "Process Finished"
End Sub
Now, execute the project and click the command button which will invoke calculator application and waits until it finishes. When the calculator is closed, it'll popup a message 'Process Finished'.
The button click event passes 'CALC.EXE' command line to ExecCmd procedure. ExecCmd will invoke calc.exe and get the handle, using the handle it will call 'WaitForSingleObject' API. This will be called until it returns 258 which means until the calculator is closed. So when the calculator is closed, it will come out from the loop and returns to click event, then 'process finished' message will be displayed.