We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

How to check if another application is still running?

Lewis
Lewis asked
on
Medium Priority
194 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).
Comment
Watch Question

Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
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

Author

Commented:
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.

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

Author

Commented:
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

Commented:
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

Author

Commented:
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.

Commented:
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.

Author

Commented:
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

Author

Commented:
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
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.