Using the Shell method, in any version of Visual Basic, does not allow you to do this. You will need to use an API call and wait for the called program to end. We will discuss how to do this in 16-bit versions of Visual Basic and 32-bit versions.
Shelling From Visual Basic 16-bit
This code will work under any 16-bit version of Visual Basic. Waiting for a program to end is simple.
Declare Function GetModuleUsage Lib "Kernel" (ByVal _
hModule As Integer) As Integer
Declare Function WinExec Lib "Kernel" (ByVal lpCmdLine _
As String, ByVal nCmdShow As Integer) As Integer
Global Const SW_HIDE = 0
Global Const SW_SHOWNORMAL = 1
Global Const SW_NORMAL = 1
Global Const SW_SHOWMINIMIZED = 2
Global Const SW_SHOWMAXIMIZED = 3
Global Const SW_MAXIMIZE = 3
Global Const SW_SHOWNOACTIVATE = 4
Global Const SW_SHOW = 5
Global Const SW_MINIMIZE = 6
Global Const SW_SHOWMINNOACTIVE = 7
Global Const SW_SHOWNA = 8
Global Const SW_RESTORE = 9
Sub DoShell (sShellString As String, iWinType As Integer)
Dim iInstanceHandle As Integer
Dim X As Integer
iInstanceHandle = WinExec(sShellString, iWinType)
Do While GetModuleUsage(iInstanceHandle) > 0
X = DoEvents()
DoShell "C:\DOS\FORMAT.COM", SW_HIDE
This code uses the WinExec API call to start the program and return the instance handle. We simply sit in a DoEvents loop until GetModuleUsage (using the instance handle as the parameter) tells us that the instance of that called program is gone. You also can start the program in any of the SW_ modes you like, including hiding it!
Shelling From Visual Basic 32-bit
Shelling from a 16-bit version of Visual Basic is easy. Things are not so easy in 32-bit environments. With Windows 95 or Windows NT, every program runs its own distinct environment, which precludes polling if an instance of a program still exists. The following code will do the trick.
Declare Function OpenProcess Lib "kernel32" (ByVal _
dwDesiredaccess&, ByVal bInherithandle&, _
ByVal dwProcessid&) As Long
Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, lpexitcode As Long) As Long
Const STILL_ACTIVE = &H103
Const PROCESS_QUERY_INFORMATION = &H400
Sub ShellWait(sCommandLine As String)
Dim hShell As Long
Dim hProc As Long
Dim lExit As Long
hShell = Shell(sCommandLine, vbNormalFocus)
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, _
GetExitCodeProcess hProc, lExit
Loop While lExit = STILL_ACTIVE
The trick with this code, as opposed to the method that the Microsoft KnowledgeBase has, is that it Shells the required program and then opens a process. It then waits for that process to finish. This way, if the program you Shelled calls other programs, you can continue on after the main (parent) program closes.
For example, if you Shelled the Internet Explorer, and the user started a download, you would not be able to continue until that download is done, even if the user closed Explorer. There might be times when you require this behavior (refer to article Q96844 of the Visual Basic KnowledgeBase). That code gives you an alternative.
This tip is reprinted from the VB Tips & Tricks Volume 1 book.