Solved

How to check if another application is still running?

Posted on 1998-09-03
10
169 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

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…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
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…

758 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now