Solved

How to check if another application is still running?

Posted on 1998-09-03
10
172 Views
Last Modified: 2010-04-30
I have written a small VB program that launches another
program and checks periodically if it is still running.
After the termination of the other program I print out the
ellapsed time.

I start the other program with Shell( path, vbMinimizedNoFocus ).
In order to check if it has finished I put in a timer
that every 5 seconds uses AppActivate ShellID with the
ID returned from the Shell command. If AppActivate returns
an error I know that the other application has terminated
and I can put out the approximate time it took (with a
maximum error of 5 seconds).

Is there a better way to test if another application is
still running (has terminated)? The most annoying thing
is that AppActivate gives the focus to the DOS window
which the other application is running in (and that happens
every five seconds because of the timer).
0
Comment
Question by:Lewis
  • 5
  • 4
10 Comments
 
LVL 9

Accepted Solution

by:
Dalin earned 350 total points
ID: 1432873
Lewis,
You can use shell and wait, no need for timer and check.

1. API Declare, form's General declaration area

          Const SYNCHRONIZE = &H100000
          Const INFINITE = &HFFFFFFFF
          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 WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

         
     2.  Usage

          Dim pId As Long, pHnd As Long '

          pId = Shell("Notepad", vbNormalFocus) '

          pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' get Process Handle
          If pHnd <> 0 Then
              Call WaitForSingleObject(pHnd, INFINITE) ' Wait until shelled prog ends
              Call CloseHandle(pHnd)
          ' Now record the time
          End If

Regards
Dalin
0
 
LVL 3

Expert Comment

by:a111a111a111
ID: 1432874
Hi, I don't need any points here.

Here is an example to record the time of Dalin Program (A real great one).

=============== start ============

Option Explicit
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF
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 WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Private Sub Command1_Click()
Dim pId As Long, pHnd As Long '
Dim StartTime
Dim EndTime
Dim TimePassed

StartTime = Timer

pId = Shell("Notepad", vbNormalFocus) '

pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' get Process Handle
If pHnd <> 0 Then
    Call WaitForSingleObject(pHnd, INFINITE) ' Wait until shelled prog ends
    Call CloseHandle(pHnd)
    ' Now record the time
    EndTime = Timer
    TimePassed = (EndTime - StartTime)
    MsgBox TimePassed
    'or label or file....

End If

End Sub


============ end ============

http://www.hili.com/~shay
0
 

Author Comment

by:Lewis
ID: 1432875
Thanks guys, that's close to what I wanted. But I have a couple of option buttons
on my form, each designating another application. As soon as one of them is
launched, I disable the execute button for this specific application. But I still want
to be able to launch the other ones (or even run multiple instances of one application
at the same time in a future release).

The timer allows me to keep my program running while the launched application
performs in the background. Using Dalin's approach my program would need to
wait till one has finished.

Is there some kind of event that can be triggered if another process terminates so that
I can then calculate the time and print out some statistics based on the process ID?

I increase the points, since this is potentially harder to solve.
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
LVL 9

Expert Comment

by:Dalin
ID: 1432876
Lewis,
So the two apps you are running are DOS apps (has no windows) or Window apps?
Dalin
0
 

Author Comment

by:Lewis
ID: 1432877
Hi Dalin,
they are DOS applications. They are ready made, the VB program was only written
to give the user a nice looking interface in order to launch those apps. Since they
do not disturb each other it should be possible to launch two or more of them so
that they run kind of simultaneously. It would be perfect to even have multiple instances
of the same app, but that is not as critical right now.

As a quick fix for that AppActivate problem, do you know another function that checks
if another app is still running without giving the focus to the other window?

Lewis
0
 
LVL 9

Expert Comment

by:Dalin
ID: 1432878
Lewis,
Try this, see if this solve your problem

1. In the general declaration area of your form (form1), add:
       Private Declare Function GetForegroundWindow Lib "user32" () As Long

       2. drop a timer to your form, name it tmrGetFocus, set the interval to 50 (you can adjust this).

       3. in the tmrGetFocus_timer event, add:

       If GetForegroundWindow()<>me.hwnd then  me.show

  Let me know if you have more problems.

Regards
Dalin
0
 

Author Comment

by:Lewis
ID: 1432879
Hey Dalin,
very nice, unfortunately my program would dominate the system afterwards, taking
the focus constantly. Pretty much the same I had before just the other way around  ;-)
Isn't there a command that simply checks if a window is still active given a known
handle, ID  or something?

By the way, where do I find documentation on kernel32, user32, and all these
other nice libs?

A quite impressed
Lewis.
0
 
LVL 9

Expert Comment

by:Dalin
ID: 1432880
Lewis,
You can adjust the intervals to adjust the focus. I thought they were DOS apps so they can pretty much run without focus. Do you have other apps running at the same time?

There may be other ways.  I just did not have a full picture of what your situation.

You can find all the API document in the Microsoft MSDN  on line library.  goto: http://premium.microsoft.com/msdn/library/?FinishURL=/msdn/library/,  and click on SDK Doc/Plateform/Reference, you should see Win32 functions either by Alphabetic or by category.
0
 

Author Comment

by:Lewis
ID: 1432881
Right, they are independent programs, the whole AppActivate stuff only takes place
because I do not know a better way to find out if these programs are still running.
By calling AppActivate I receive an error if not, which shows me that it terminated.
Then I can calculate the elapsed time and (more important) launch an appropriate
follow-up process. Disadvantage, as stated earlier, I give the focus to that DOS window.
The five seconds I use is just a compromise.

I would like to find a function that just scans for an active application (or window)
without activating it. That way I could continue working with any other application without
loosing focus constantly. I will take a look at the documentation you pointed out.

If you do not have another idea I will close this question soon and award you your
points. Although my problem is still looming you provided interesting insights!

Thanks,
Lewis
0
 

Author Comment

by:Lewis
ID: 1432882
Hi Dalin,
I found the stuff I need on the page you pointed out. Here is the solution, I already
adapted it into my own code:

1.Create a new project in Visual Basic. Form1 is created by default.

   2.Add the following Constant and Declare statements to the General Declarations section of Form1 (note that each Declare statement must be
     typed as a single line of 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

   3.Add a Command Button control to Form1. Command1 is created by default.

   4.Add the following code to the Click event for Command1:

     Private Sub Command1_Click()
         Dim JobToDo As String
         JobToDo = "c:\windows\notepad.exe"
         Shell32Bit JobToDo
     End Sub

   5.Create a new subroutine called Shell32Bit. Add the following code to this subroutine:

     Sub Shell32Bit(ByVal JobToDo As String)
         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, 6))
         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 "Notepad terminated by user"
     End Sub

Run the example program by pressing f5. Click the Command Button control. The example program runs the Windows Notepad
application. Notice that the Notepad icon appears in the Windows taskbar.

Problem solved, thanks,
Lewis
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
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…

831 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