Results 1 to 10 of 10

Thread: Come on experts answer this.

  1. #1
    Guest

    Lightbulb

    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?

  2. #2
    Guest
    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

  3. #3
    Guest
    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?

  4. #4
    Hyperactive Member
    Join Date
    Jul 2000
    Location
    Halifax,UK
    Posts
    274
    You could find the applications handle and do loop until it doesn't exist any more.

    regards

    Chris
    VB6 VS2005

  5. #5
    Guest
    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?

  6. #6
    Guest
    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

  7. #7
    _______ HeSaidJoe's Avatar
    Join Date
    Jun 1999
    Location
    Canada
    Posts
    3,946

    <?>

    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

  8. #8
    Guest
    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.

  9. #9
    Guru Yonatan's Avatar
    Join Date
    Apr 1999
    Location
    Israel
    Posts
    892
    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]

  10. #10
    Guest
    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
  •  



Click Here to Expand Forum to Full Width