sye
asked on
Create process with 16 bit apps
I am using the createprocess API along with WaitforSingle Object the 16 bit app starts but goes nowhere. If I kill the VB5 app that calls it the 16 bit app finishes. It seems to be hanging at the Waitforsingleobject API is there something i can do to make this process continue. This works fine on a NT machine the problem seems to only occur on win95 machines.
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
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 Sub ExecCmd(cmdline$)
Dim Proc As PROCESS_INFORMATION
Dim Start As STARTUPINFO
' Initialize the STARTUPINFO structure:
Start.cb = Len(Start)
' Start the shelled application:
ret& = CreateProcess(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, Start, Proc)
' Wait for the shelled application to finish:
ret& = WaitForSingleObject(Proc.h Process, INFINITE)
ret& = CloseHandle(Proc.hProcess)
End Sub
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
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 Sub ExecCmd(cmdline$)
Dim Proc As PROCESS_INFORMATION
Dim Start As STARTUPINFO
' Initialize the STARTUPINFO structure:
Start.cb = Len(Start)
' Start the shelled application:
ret& = CreateProcess(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, Start, Proc)
' Wait for the shelled application to finish:
ret& = WaitForSingleObject(Proc.h
ret& = CloseHandle(Proc.hProcess)
End Sub
ASKER
This is similar to the othe rquestion I tried it with the same results the 16 bit app starts and waits for the VB5 app to be killed before it will proceed any further or be killed itself.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I tried calling the 16 bit ap with the command /c "app" nothing seemed to happen the called app did not start. We need it to start allow the user to manipulate some things then close it and have the vb5 app pick up where it stopped. The 16 bit app starts it just hangs (the logo for the app is not even displayed) then if i close the vb app from the task list the app continues as i want it to.
I see!
You don't want the the caller application to freeze, for that I think it's better for you to use the following function.
If you look into the function you can see that I'm using a loop to see if the DOS Window begins with the caption FINISHED, you put the code you need in there, like a DoEvents so that you application dont frezes
Option Explicit
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject 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)
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Const STILL_ACTIVE = &H103
Private Const PROCESS_QUERY_INFORMATION = &H400
Private Const SYNCHRONIZE = &H100000
Public Const WAIT_FAILED = -1& 'Error on call
Public Const WAIT_OBJECT_0 = 0 'Normal completion
Public Const WAIT_ABANDONED = &H80& '
Public Const WAIT_TIMEOUT = &H102& 'Timeout period elapsed
Public Const IGNORE = 0 'Ignore signal
Public Const INFINITE = -1& 'Infinite timeout
Public Const SW_HIDE = 0
Public Const SW_SHOWNORMAL = 1
Public Const SW_SHOWMINIMIZED = 2
Public Const SW_SHOWMAXIMIZED = 3
Public Const SW_SHOWNOACTIVATE = 4
Public Const SW_SHOW = 5
Public Const SW_MINIMIZE = 6
Public Const SW_SHOWMINNOACTIVE = 7
Public Const SW_SHOWNA = 8
Public Const SW_RESTORE = 9
Private Const WM_CLOSE = &H10
Private Const GW_HWNDNEXT = 2
Private Const GW_OWNER = 4
Public Function ShellAndClose(ByVal JobToDo As String, Optional ExecMode) As Long
'
' Shells a new process and waits for it to complete.
' Calling application is responsive while new process
' executes. It will react to new events, though execution
' of the current thread will not continue.
'
' Will close a DOS box when Win95 doesn't. More overhead
' than ShellAndLoop but useful when needed.
'
Dim ProcessID As Long
Dim PID As Long
Dim hProcess As Long
Dim hWndJob As Long
Dim nRet As Long
Dim TitleTmp As String
Const fdwAccess = PROCESS_QUERY_INFORMATION
If IsMissing(ExecMode) Then
ExecMode = vbMinimizedNoFocus
Else
If ExecMode < vbHide Or ExecMode > vbMinimizedNoFocus Then
ExecMode = vbMinimizedNoFocus
End If
End If
On Error Resume Next
ProcessID = Shell(JobToDo, CLng(ExecMode))
If Err Then
ShellAndClose = vbObjectError + Err.Number
Exit Function
End If
On Error GoTo 0
hWndJob = FindWindow(vbNullString, vbNullString)
Do Until hWndJob = 0
If GetParent(hWndJob) = 0 Then
Call GetWindowThreadProcessId(h WndJob, PID)
If PID = ProcessID Then Exit Do
End If
hWndJob = GetWindow(hWndJob, GW_HWNDNEXT)
Loop
hProcess = OpenProcess(fdwAccess, False, ProcessID)
Do
TitleTmp = Space(256)
nRet = GetWindowText(hWndJob, TitleTmp, Len(TitleTmp))
If nRet Then
TitleTmp = UCase(Left(TitleTmp, nRet))
If InStr(TitleTmp, "FINISHED") = 1 Then
Call SendMessage(hWndJob, WM_CLOSE, 0, 0)
End If
End If
GetExitCodeProcess hProcess, nRet
DoEvents
Sleep 100
Loop While nRet = STILL_ACTIVE
Call CloseHandle(hProcess)
ShellAndClose = nRet
End Function
You don't want the the caller application to freeze, for that I think it's better for you to use the following function.
If you look into the function you can see that I'm using a loop to see if the DOS Window begins with the caption FINISHED, you put the code you need in there, like a DoEvents so that you application dont frezes
Option Explicit
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject 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)
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Const STILL_ACTIVE = &H103
Private Const PROCESS_QUERY_INFORMATION = &H400
Private Const SYNCHRONIZE = &H100000
Public Const WAIT_FAILED = -1& 'Error on call
Public Const WAIT_OBJECT_0 = 0 'Normal completion
Public Const WAIT_ABANDONED = &H80& '
Public Const WAIT_TIMEOUT = &H102& 'Timeout period elapsed
Public Const IGNORE = 0 'Ignore signal
Public Const INFINITE = -1& 'Infinite timeout
Public Const SW_HIDE = 0
Public Const SW_SHOWNORMAL = 1
Public Const SW_SHOWMINIMIZED = 2
Public Const SW_SHOWMAXIMIZED = 3
Public Const SW_SHOWNOACTIVATE = 4
Public Const SW_SHOW = 5
Public Const SW_MINIMIZE = 6
Public Const SW_SHOWMINNOACTIVE = 7
Public Const SW_SHOWNA = 8
Public Const SW_RESTORE = 9
Private Const WM_CLOSE = &H10
Private Const GW_HWNDNEXT = 2
Private Const GW_OWNER = 4
Public Function ShellAndClose(ByVal JobToDo As String, Optional ExecMode) As Long
'
' Shells a new process and waits for it to complete.
' Calling application is responsive while new process
' executes. It will react to new events, though execution
' of the current thread will not continue.
'
' Will close a DOS box when Win95 doesn't. More overhead
' than ShellAndLoop but useful when needed.
'
Dim ProcessID As Long
Dim PID As Long
Dim hProcess As Long
Dim hWndJob As Long
Dim nRet As Long
Dim TitleTmp As String
Const fdwAccess = PROCESS_QUERY_INFORMATION
If IsMissing(ExecMode) Then
ExecMode = vbMinimizedNoFocus
Else
If ExecMode < vbHide Or ExecMode > vbMinimizedNoFocus Then
ExecMode = vbMinimizedNoFocus
End If
End If
On Error Resume Next
ProcessID = Shell(JobToDo, CLng(ExecMode))
If Err Then
ShellAndClose = vbObjectError + Err.Number
Exit Function
End If
On Error GoTo 0
hWndJob = FindWindow(vbNullString, vbNullString)
Do Until hWndJob = 0
If GetParent(hWndJob) = 0 Then
Call GetWindowThreadProcessId(h
If PID = ProcessID Then Exit Do
End If
hWndJob = GetWindow(hWndJob, GW_HWNDNEXT)
Loop
hProcess = OpenProcess(fdwAccess, False, ProcessID)
Do
TitleTmp = Space(256)
nRet = GetWindowText(hWndJob, TitleTmp, Len(TitleTmp))
If nRet Then
TitleTmp = UCase(Left(TitleTmp, nRet))
If InStr(TitleTmp, "FINISHED") = 1 Then
Call SendMessage(hWndJob, WM_CLOSE, 0, 0)
End If
End If
GetExitCodeProcess hProcess, nRet
DoEvents
Sleep 100
Loop While nRet = STILL_ACTIVE
Call CloseHandle(hProcess)
ShellAndClose = nRet
End Function
Bought This Question.
Sorry, but I didn't understand what you said?
There is a similar question in the locked question area.
If thtat works, you can delete the question and save you some points.
Regards
Dalin