|
-
Sep 22nd, 2000, 08:52 AM
#1
Ok, so now I've got your attention.
I need a routine that will allow me to run another application and detect when it has finished loading.
I don't meen using the shell command I meen 32Bit Windows applications.
I don't even know if this is possible, anyone got any ideas?
-
Sep 22nd, 2000, 09:02 AM
#2
The Shell function in VB will start another (Win32) application, and return a long with the program's ID if it was successful or a 0 if it wasn't.
However, the problem with this is that Shell is asynchronous. Meaning the code after the Shell function might execute before the program that Shell started finishes starting up so checking if Shell returned a zero straight after the Shell function is not always a good idea.
Sunny
-
Sep 22nd, 2000, 09:09 AM
#3
Ok so maybe I can use the shell command.
Are you saying that I could keep checking the value returned from the shell command until the application is loaded?
I assumed that you could only get a single value that will be returned as soon as the shell command is run?
I need to keep checking to see if an application has finished loading and then get the vb program to react.
If this can be done with shell can you give a code example?
-
Sep 22nd, 2000, 09:11 AM
#4
Hyperactive Member
You could find the applications handle and do loop until it doesn't exist any more.
regards
Chris
-
Sep 22nd, 2000, 09:15 AM
#5
If I check for the window handle that will tell me when the application appears in memory but not when it has finished loading.
It would be ok to check if an application has been closed but not when it has finished loading.
If I am wrong then give me an example of how you might do it?
-
Sep 22nd, 2000, 09:19 AM
#6
You could loop until the value is not equal to zero, but this essentially means that you program must start, otherwise VB goes into an endless loop (unless you have some cancel function), or an API that can check for exisiting windows (which I admit I'm not good with).
Code:
Option Explicit
Dim StopNow As Boolean
Private Sub Form_Load()
Dim i As Long
StopNow = False
i = Shell("c:\windows\calc.exe")
Do Until i <> 0
DoEvents
If StopNow = True Then
StopNow = False
Exit Do
End If
Loop
MsgBox "loaded"
End Sub
Private Sub Command1_Click() 'cancel
StopNow = True
End Sub
Feel free to flame me for using DoEvents.
Sunny
-
Sep 22nd, 2000, 09:26 AM
#7
_______
<?>
Code:
'uses Timer1, Form1,Command1
'~~~~~~~MODULE CODE~~~~~~~~~~~~
Option Explicit
Public Const WM_CLOSE = &H10
Public Const MAX_PATH = 260
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
Declare Function EnumWindows Lib "user32" _
(ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private sAppTitle As String
Public glHwnd As Long
Public Function fEnumWindowsCallBack(ByVal hwnd As Long, ByVal lpData As Long) As Long
Dim lResult As Long
Dim sWndName As String
fEnumWindowsCallBack = 1
sWndName = Space$(MAX_PATH)
lResult = GetWindowText(hwnd, sWndName, MAX_PATH)
sWndName = Left$(sWndName, lResult)
'Search Title for our string
If (InStr(1, sWndName, sAppTitle, vbTextCompare) > 0) Then
Debug.Print sWndName
glHwnd = hwnd
fEnumWindowsCallBack = 0
End If
End Function
Public Function SearchWindows(sApp As String, hwnd As Long) As Long
sAppTitle = sApp
glHwnd = 0
Call EnumWindows(AddressOf fEnumWindowsCallBack, hwnd)
SearchWindows = glHwnd
End Function
'~~~~~~~FORM CODE~~~~~~~~~~~~~~
Option Explicit
Private Sub Command1_Click()
Dim RetVal
RetVal = Shell("C:\WINDOWS\notepad.exe C:\WINDOWS\mytext.txt")
End Sub
Private Sub Form_Load()
Timer1.Interval = 1
End Sub
Private Sub Timer1_Timer()
Dim sApp As String
'Find notepad with partial name
sApp = "notepa"
glHwnd = SearchWindows(sApp, Me.hwnd)
'End application if found
If glHwnd > 0 Then
'do whatever you want to do
MsgBox "yes it is loaded"
Timer1.Enabled = False
Else
'do nothing
End If
End Sub
"A myth is not the succession of individual images,
but an integerated meaningful entity,
reflecting a distinct aspect of the real world."
___ Adolf Jensen
-
Sep 22nd, 2000, 09:42 AM
#8
Thanks both your posts seem to offer good solutions
I will need to test them a little more before I can be sure however.
HesaidJoe, can you be sure that when an application appears in the Hwnd list that it is fully loaded?
Could it be still processing?
Thanks for the good ideas anyway.
-
Sep 22nd, 2000, 10:03 AM
#9
Guru
Too much code, HeSaidJoe! 
sunnyl: Flame! The variable i cannot change without i = ....
DoEvents is ok, though. I used it in the following working short example:
Code:
Option Explicit
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
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 Const SYNCHRONIZE = &H100000
Private Const WAIT_FAILED = &HFFFFFFFF
Private Const WAIT_TIMEOUT = &H102&
Function SyncShell(PathName, Optional WindowStyle As VbAppWinStyle = vbMinimizedFocus) As Long
Dim dwProcessID As Long, hProcess As Long, lState As Long
On Error GoTo ErrorHandler
SyncShell = -1
dwProcessID = Shell(PathName, WindowStyle)
If dwProcessID = 0 Then Exit Function
hProcess = OpenProcess(SYNCHRONIZE, False, dwProcessID)
If hProcess = 0 Then Exit Function
Do
DoEvents
lState = WaitForSingleObject(hProcess, 0)
If lState = WAIT_FAILED Then
Call CloseHandle(hProcess)
Exit Function
End If
Loop While lState = WAIT_TIMEOUT
Call CloseHandle(hProcess)
SyncShell = 0
Exit Function
ErrorHandler:
SyncShell = Err.Number
Call CloseHandle(hProcess)
End Function
Use SyncShell exactly like Shell.
It returns zero on success.
On failure:
If it's an API error, it returns -1 and the error number is stored in Err.LastDllError.
If it's a VB runtime error, it returns the error number.
[Edited by Yonatan on 09-22-2000 at 11:09 AM]
-
Sep 22nd, 2000, 02:15 PM
#10
Try this:
Code:
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
'JobtoDo - Program to run
'frm - Form
'You can do anything after the loop..shell another program if that program is close, load another version of your app, etc.
Sub Shell32Bit(ByVal JobToDo As String, frm As Form)
Dim hProcess As Long
Dim RetVal As Long
'The next line launches JobToDo as icon,
'captures process ID
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, Shell(JobToDo, 1))
Do
'Get the status of the process
GetExitCodeProcess hProcess, RetVal
'Sleep command recommended as well as DoEvents
DoEvents: Sleep 100
'Loop while the process is active
Loop While RetVal = STILL_ACTIVE
Msgbox "Application is finished!", 48
End Sub
Usage:
Private Sub Command1_Click()
Call Shell32Bit("C:\App\App.exe", Me)
End Sub
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|