NguyenHuy
asked on
VB6 - How to wait for process to finish
Hi All,
I need to write a customizable installation program which has this process sequence:
- Install MS Access runtimes (\Access\setup.exe)
- Install our program (\Ours\setup.exe)
- Install MSDE 2000 (\MSDE\setup.exe)
This is the function I use to run those setup.exe
-----------------------
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 Function ExecCmd(commandline, Optional nothing1 As Variant)
'nothing1 is included to be compatible with shell(command, windowstyle)
Dim proc As PROCESS_INFORMATION
Dim Start As STARTUPINFO
Dim ReturnValue As Integer
cmdline$ = commandline
' 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.h Process, 0)
DoEvents
Loop Until ReturnValue <> 258
ReturnValue = CloseHandle(proc.hProcess)
ExecCmd = ReturnValue
End Function
---------------
The thing is no matter I wait for single object to excute. It still does not stop. All 3 setup program just trying to run all together. Can ne1 help? Do you have any better solution for this problem?
I need to write a customizable installation program which has this process sequence:
- Install MS Access runtimes (\Access\setup.exe)
- Install our program (\Ours\setup.exe)
- Install MSDE 2000 (\MSDE\setup.exe)
This is the function I use to run those setup.exe
-----------------------
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 Function ExecCmd(commandline, Optional nothing1 As Variant)
'nothing1 is included to be compatible with shell(command, windowstyle)
Dim proc As PROCESS_INFORMATION
Dim Start As STARTUPINFO
Dim ReturnValue As Integer
cmdline$ = commandline
' 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.h
DoEvents
Loop Until ReturnValue <> 258
ReturnValue = CloseHandle(proc.hProcess)
ExecCmd = ReturnValue
End Function
---------------
The thing is no matter I wait for single object to excute. It still does not stop. All 3 setup program just trying to run all together. Can ne1 help? Do you have any better solution for this problem?
Try this tiny little piece of software called iexpress. Click start > run > and type iexpress. It is one of the hidden candies in win2K & XP. What it does, it packes files into on exe selfextract file. So, you can tell iexpress to run installation one before the main installation, and installation three after the main installation. Check it. It might help.
S
S
Or try this shellwait function:
Private Declare Function OpenProcess Lib "Kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "Kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long)
Const STILL_ACTIVE = &H103
Const PROCESS_QUERY_INFORMATION = &H400
Private Function ShellWait(PathName, Optional WindowStyle As VbAppWinStyle = vbNormalFocus) As Double
Dim hProcess As Long, RetVal As Long
hProcess = OpenProcess(PROCESS_QUERY_ INFORMATIO N, False, Shell(PathName, WindowStyle))
Do
GetExitCodeProcess hProcess, RetVal
DoEvents: Sleep 100
Loop While RetVal = STILL_ACTIVE
End Function
Private Sub Command1_Click()
ShellWait "\Access\setup.exe", vbNormalFocus
ShellWait "\Ours\setup.exe", vbNormalFocus
ShellWait "\MSDE\setup.exe", vbNormalFocus
End Sub
Private Declare Function OpenProcess Lib "Kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "Kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long)
Const STILL_ACTIVE = &H103
Const PROCESS_QUERY_INFORMATION = &H400
Private Function ShellWait(PathName, Optional WindowStyle As VbAppWinStyle = vbNormalFocus) As Double
Dim hProcess As Long, RetVal As Long
hProcess = OpenProcess(PROCESS_QUERY_
Do
GetExitCodeProcess hProcess, RetVal
DoEvents: Sleep 100
Loop While RetVal = STILL_ACTIVE
End Function
Private Sub Command1_Click()
ShellWait "\Access\setup.exe", vbNormalFocus
ShellWait "\Ours\setup.exe", vbNormalFocus
ShellWait "\MSDE\setup.exe", vbNormalFocus
End Sub
ASKER
Thank you guys. I will try every method tomorrow when get back to work. Will reply shortly
Do
ReturnValue = WaitForSingleObject(proc.h Process, 0)
DoEvents
Loop Until ReturnValue <> 258
I think you need
Loop While ReturnValue <> 258
Except of this, it's better to replace second parameter of WaitForSingleObject with non-null value, like:
ReturnValue = WaitForSingleObject(proc.h Process, 100)
This gives more time to another process.
ReturnValue = WaitForSingleObject(proc.h
DoEvents
Loop Until ReturnValue <> 258
I think you need
Loop While ReturnValue <> 258
Except of this, it's better to replace second parameter of WaitForSingleObject with non-null value, like:
ReturnValue = WaitForSingleObject(proc.h
This gives more time to another process.
Oops, sorry. Ignore my post (at least, it's first part).
I think your code is OK, but there are some processes which launch another process and exit immidiately. Program that tries to wait for such process continues - this happens, for example, when we run by such way Windows Explorer. Try this code with simple process like Notepad to see whether problem is in your code or in process itself.
Or
Dim wshShell
Set wshShell = CreateObject("WScript.Shel l")
wshShell.Run "c:\notepad.exe", 1, true
Set wshShell = Nothing
Dim wshShell
Set wshShell = CreateObject("WScript.Shel
wshShell.Run "c:\notepad.exe", 1, true
Set wshShell = Nothing
ASKER
Today finally I got my time to test your solution
The Baker, thanks for your suggestion. I have visited that page before posting question here. The solution works somewhere else but not for me
Shauli, thanks for the tiny little gem. I did not know that XP has a self extractor program. Unfortunately that not what Im looking for.
Vin, thanks your code does not work for me. I cant explain why but I got the same result as my code.
Alex, I think you are correct. However when I try paquet builder 2.8 shareware version, it does the job nicely. So it means that there must be a way to work around this problem. I can afford to pay $30 for paquet builder, but having total control of the setup program in my hands is better anywayz.
Please let me know if you know anything good. Im willing to try anything possible
The Baker, thanks for your suggestion. I have visited that page before posting question here. The solution works somewhere else but not for me
Shauli, thanks for the tiny little gem. I did not know that XP has a self extractor program. Unfortunately that not what Im looking for.
Vin, thanks your code does not work for me. I cant explain why but I got the same result as my code.
Alex, I think you are correct. However when I try paquet builder 2.8 shareware version, it does the job nicely. So it means that there must be a way to work around this problem. I can afford to pay $30 for paquet builder, but having total control of the setup program in my hands is better anywayz.
Please let me know if you know anything good. Im willing to try anything possible
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
That might help. It shows you how to wait for a process started with Shell() to finish before continuing with your own app. So if you changed your code to run with shell, then it should work. Or you may be able to adapt it if you don't want to change the way you start your programs.
TheBaker