?
Solved

Launching and then reactivating another app from VB5

Posted on 1999-06-25
11
Medium Priority
?
367 Views
Last Modified: 2011-09-20
I need to launch another application from my VB5 app. No problem using Shell, but if the user switches back to the 1st app and then tries to launch the second app again, I need to see if it is running already, and if so restore it whether it is minimized or not. If it was closed, I know I can just use shell again. The code I need is how to determine whether it is running. FindWindow API won't do because the second app is an MDI and the Caption varies depending on the child windows caption. Thanks.
0
Comment
Question by:arniels
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
11 Comments
 

Author Comment

by:arniels
ID: 1519751
Adjusted points to 200
0
 
LVL 12

Expert Comment

by:mark2150
ID: 1519752
When you fire the SHELL you get a return value. Before you fire it a second time try an App.Activate and see if you get an error #5 back. If the app is still hot, it'll come to the front. If it's been closed the error tells you to fire SHELL again.

M

0
 

Author Comment

by:arniels
ID: 1519753
Mark2150 has come close. Yes, using AppActivate returns an error and I can then Shell again if the app is not running. If the app is running, it will then activate. But, if it is running and it is minimized, this method will not activate and restore the app as a normal window.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 10

Expert Comment

by:viktornet
ID: 1519754
here is what you do... you gotta assign your main form a unique class name... then you simply use FindWindow() by using the class parameter and not the caption, and if the handle returned is different than 0 then the app is running, otherwise it is not...

..-=ViKtOr=-..
0
 

Author Comment

by:arniels
ID: 1519755
Thanks, but the app I am shelling to may be someone elses and I cannot assign or may not know the Class Name.
0
 
LVL 12

Expert Comment

by:mark2150
ID: 1519756
App.Activate certainly *SHOULD* maximize the app! I use Adobe Acrobat as a child task and it enlarges just fine!

Let me get the code (hang on!)

... time passes ...

Ok, here is how I launch the app:

RetVal = Shell(Quote & Adobe_Path & Quote, vbMaximizedFocus)

This is sub that brings the app to the top and drives it:

Private Sub sendit(txt As String)
'
' Send string to child task
'
On Error Resume Next    'Ignore any errors that occur
AppActivate RetVal      'Make sure child task is active
DoEvents                'Give it a shot to run
SendKeys txt, True      'Tell it what to do and wait
DoEvents                'Cede some more time
'
End Sub


This is a sample code sequence I send:

Call log("Accessing Document: " & filename & " Page " & onpage, "I", vbBlue)
'
sendit ("%WA")                      'Close all windows
sendit ("%FO" & datadrive & RefPath & "\" & filename & "{enter}")
sendit ("%VG")                      ' Issue page select command
sendit (onpage & "{enter}")         ' Specify page

This code works like a top and every time a SENDIT is issued, the app comes to the top even if the operator has minimized it.

M


0
 
LVL 3

Expert Comment

by:KhollAD
ID: 1519757
you can try the code below :

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long

Private Const GW_CHILD = 5
Private Const GW_HWNDNEXT = 2

Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Const SW_RESTORE = 9

Dim HprocessProgram As Long
Dim HwndProgram As Long


Private Sub Command1_Click()

Dim lRes As Long

If HwndProgram = 0 Then 'not running --> shell
    HprocessProgram = Shell("myapp.exe", vbNormalFocus)
    HwndProgram = GetWindowHandle(HprocessProgram)
Else
    lRes = ShowWindow(HwndProgram, SW_RESTORE) 'running --> show
    If lRes = 0 Then 'previously running, now, not runnnig --> shell
        HprocessProgram = Shell("myapp.exe", vbNormalFocus)
        HwndProgram = GetWindowHandle(HprocessProgram)
    End If
End If

End Sub
Private Function GetWindowHandleLow(ByVal hWndStart As Long, hProcess As Long)
Dim c_hWnd As Long
Dim hWndReturn As Long
Dim hProcessCur As Long

'Get first child
Dim c As Long
c_hWnd = GetWindow(hWndStart, GW_CHILD)



'loop through all children
Do Until c_hWnd = 0

    'Get the window's process handle
    GetWindowThreadProcessId c_hWnd, hProcessCur
   
    'if the process handle matches, return the window's handle
    If hProcessCur = hProcess Then
        GetWindowHandleLow = c_hWnd
        Exit Function
    End If
   
    'search all of the children of this window
    hWndReturn = GetWindowHandleLow(c_hWnd, hProcess)
   
    'return handle to caller if non-zero
    If hWndReturn <> 0 Then
        GetWindowHandleLow = hWndReturn
        Exit Function
    End If
   
    'no match get the next window
   
    c_hWnd = GetWindow(c_hWnd, GW_HWNDNEXT)

Loop

'return window handle not found
GetWindowHandleLow = 0

End Function

Private Function GetWindowHandle(hProcess As Long) As Long

'Recursively collect all of the window handless
'to search for the process handle (hprocess).
'return to caller (0 if not found)

GetWindowHandle = GetWindowHandleLow(GetDesktopWindow, hProcess)

End Function



0
 

Author Comment

by:arniels
ID: 1519758
AppActivate doe not restore a minimized app. KHollAD's solution works fine if there is no splash screen or login screen preceeding the main mdi form, but it there is, it gets the hwnd of the login form which will not be opened when you want to reactivate the app.

I have tried the following code and it seems to work. If anyone has a better approach, let me know.

Public Sub RunApp(frm As Form, spath As String, sparam As String, stitle As String)

'where frm is the calling form, spath is the path and exe 'to run, sparam is is any command parameter, and stitle is 'the app caption to search

'(e.g. RunApp Me, "C:\folder\myapp.exe", "/Command", '"Parent Caption")

Dim hwndcurr As Long
Dim nlen As Integer
Dim wtitle As String
Dim x As Long
Dim apprunning As Boolean
Dim stitlelen As Integer

'get the length of the caption passed
'this should be just the parent part of the caption
stitlelen = Len(stitle)
apprunning = False

'add the parameter if not null
If sparam <> "" Then
   spath = spath & " " & sparam
End If

hwndcurr = GetWindow(frm.hwnd, GW_HWNDFIRST)
'loop through windows, getting caption text, to find target 'caption
Do While hwndcurr <> 0
   nlen = GetWindowTextLength(hwndcurr)
   wtitle = Space$(nlen + 1)
   nlen = GetWindowText(hwndcurr, wtitle, nlen + 1)
   
'if target title found then activate it. Since it may be 'an mdi app, just match on parent part of caption
   If UCase$(Left$(wtitle, stitlelen)) = stitle Then
      apprunning = True
      'restore in case it is minimized
      x = ShowWindow(hwndcurr, SW_RESTORE)
      AppActivate wtitle
      Exit Do
   End If
   hwndcurr = GetWindow(hwndcurr, GW_HWNDNEXT)
Loop

'if caption not found and thus app not running
'already, launch it
If apprunning = False Then
  x = Shell(spath, 1)
End If

End Sub
0
 
LVL 2

Expert Comment

by:Torus
ID: 1519759
Or you can try this
Public bStillRunning as boolean
Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (hObject As Long) As Boolean

Dim hProcess as long
Dim lRetVal as long

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, Shell("YourExe.exe")
    Do
        GetExitCodeProcess hProcess, lRetVal
        If lRetVal <> STILL_ACTIVE Then
              bStillRunning = false
               Exit Do
        Else
              bStillRunning = true
              DoEvents
        end if
    Loop
   
    Call CloseHandle(hProcess)
end sub

Check the variable bStillRunning and you may know you launch another application or not.
0
 
LVL 1

Expert Comment

by:Maquiavelo
ID: 1519760
 I think Torus answer will do, if doesn't you can check if the EXE is running using PSAPI.DLL or sort of, that has some API functions that let you manage processes.
0
 
LVL 1

Accepted Solution

by:
poneill011098 earned 600 total points
ID: 1519761
You should be able to check for a running application by looking for it's windows by class name using the FindWindow API call - the fist argument specifies the class name.

(You will need to determine the window class name "manually" by launch the app., looking for it by caption and then retrieving it's class name using the GetClassName API first time...)

If you get a window handle back, you can activate it, otherwise you should launch the application for the first time.

0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses

718 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question