shawnlehner
asked on
Best way to wait for a launched program to exit
What is the best way to use SHELL to launch a program and pause going to the next action in your launcher program until the program you launched has finished and exited?
werk, You are talking about VB.NET.
Try the code below:
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFF
'Wait forever
Const WAIT_OBJECT_0 = 0
'The state of the specified object is signaled
Const WAIT_TIMEOUT = &H102
'The time-out interval elapsed & the object’s state
'is nonsignaled.
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Function ShellWait(txtApp As String, Optional Wait As Long = INFINITE) As Boolean
Dim lPid As Long, lHnd As Long, lRet As Long
If Trim$(txtApp) = "" Then Exit Function
Let lPid = Shell(txtApp, vbNormalFocus)
If lPid <> 0 Then
'Get a handle to the shelled process.
Let lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
'If successful, wait for the application to end and close the handle.
If lHnd <> 0 Then
lRet = WaitForSingleObject(lHnd, Wait)
Call CloseHandle(lHnd)
Let ShellWait = True
End If
End If
End Function
Private Sub Command1_Click()
Call ShellWait("notepad.exe")
End Sub
Try the code below:
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFF
'Wait forever
Const WAIT_OBJECT_0 = 0
'The state of the specified object is signaled
Const WAIT_TIMEOUT = &H102
'The time-out interval elapsed & the object’s state
'is nonsignaled.
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Function ShellWait(txtApp As String, Optional Wait As Long = INFINITE) As Boolean
Dim lPid As Long, lHnd As Long, lRet As Long
If Trim$(txtApp) = "" Then Exit Function
Let lPid = Shell(txtApp, vbNormalFocus)
If lPid <> 0 Then
'Get a handle to the shelled process.
Let lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
'If successful, wait for the application to end and close the handle.
If lHnd <> 0 Then
lRet = WaitForSingleObject(lHnd, Wait)
Call CloseHandle(lHnd)
Let ShellWait = True
End If
End If
End Function
Private Sub Command1_Click()
Call ShellWait("notepad.exe")
End Sub
A variation of Rubyn's post which keeps the app from freezing up while it is waiting for the Shelled app to exit:
Option Explicit
Private Const SYNCHRONIZE = &H100000
Private Const WAIT_TIMEOUT = &H102
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Command1_Click()
ShellAndWait "calc.exe"
MsgBox "Done"
End Sub
Private Sub ShellAndWait(ByVal cmd As String)
Dim lPid As Long
Dim lHnd As Long
lPid = Shell(cmd, vbNormalFocus)
If lPid <> 0 Then
lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
If lHnd <> 0 Then
Do
DoEvents ' keep application responsive
Sleep 50 ' keep CPU usage from ramping to 100%
Loop Until WaitForSingleObject(lHnd, 0) <> WAIT_TIMEOUT
CloseHandle (lHnd)
End If
End If
End Sub
Option Explicit
Private Const SYNCHRONIZE = &H100000
Private Const WAIT_TIMEOUT = &H102
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Command1_Click()
ShellAndWait "calc.exe"
MsgBox "Done"
End Sub
Private Sub ShellAndWait(ByVal cmd As String)
Dim lPid As Long
Dim lHnd As Long
lPid = Shell(cmd, vbNormalFocus)
If lPid <> 0 Then
lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
If lHnd <> 0 Then
Do
DoEvents ' keep application responsive
Sleep 50 ' keep CPU usage from ramping to 100%
Loop Until WaitForSingleObject(lHnd, 0) <> WAIT_TIMEOUT
CloseHandle (lHnd)
End If
End If
End Sub
A different way to do it. Also gives you back the exit code:
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Function ShellAndWait(ByVal fileName As String) As Long
If Dir(fileName) <> "" Then
Dim WShell As Object
Dim oProcess As Object
Set WShell = CreateObject("WScript.Shel l")
Set oProcess = WShell.Exec(fileName)
Do While oProcess.Status = 0
Sleep 50 ' keep CPU usage from ramping to 100%
DoEvents ' keep app responsive
Loop
ShellAndWait = oProcess.ExitCode
Set WShell = Nothing
Set oProcess = Nothing
Else
MsgBox fileName, vbCritical, "File Not Found"
ShellAndWait = 1 ' a non-zero value usually means something went wrong
End If
End Function
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Function ShellAndWait(ByVal fileName As String) As Long
If Dir(fileName) <> "" Then
Dim WShell As Object
Dim oProcess As Object
Set WShell = CreateObject("WScript.Shel
Set oProcess = WShell.Exec(fileName)
Do While oProcess.Status = 0
Sleep 50 ' keep CPU usage from ramping to 100%
DoEvents ' keep app responsive
Loop
ShellAndWait = oProcess.ExitCode
Set WShell = Nothing
Set oProcess = Nothing
Else
MsgBox fileName, vbCritical, "File Not Found"
ShellAndWait = 1 ' a non-zero value usually means something went wrong
End If
End Function
Beware since using DoEvents, Timer Controls will still trigger their methods.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Something to keep in mind... I've found that add-on apps like "Window Blinds" can mess around with process ids. That means if the method you are using relies on a process id to track if the shelled application is still running then you may get false results if something like "Window Blinds" is loaded.
Shell("programname.exe", 1, true)
the third argument (true) makes it wait until its over before continuing
heres more info on the Shell command:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vblr7/html/vafctshell.asp