Solved

How to check if another application is still running?

Posted on 1998-09-03
10
171 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
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 
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

DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
VBA saving file message display 5 67
Cannot Load VB6 on Windows 10. Installed OK but error on opening existing project. 7 87
Copy a row 12 62
Sub or Function is not defined 6 30
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
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…

777 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