Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to tell if a program is running

Posted on 1999-07-14
17
Medium Priority
?
256 Views
Last Modified: 2008-03-04
I want to write a simple VB app that determines whether another program is still running.  If it is, I want to just loop until this other program closes.  This other program is also a VB app, but it does not have a caption on Title Bar and is hidden.

Is there a way to make an API call with this program's name (SUM.EXE) and find whether or not it's running?
0
Comment
Question by:jfunderb
[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
  • 5
  • 3
  • 2
  • +5
17 Comments
 

Expert Comment

by:pakos
ID: 1524722
when u press ctrl+alt+del can u see it in the taskbar?
if yes it is to be terminated. waiting for ur answer to continue the answer
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1524723
Even if the caption is hidden, you can find it using the "FindWindow" API

If you're shelling the app from your VB project, I can give you a great procedure I wrote to shell it, and then wait til it terminates to continue.
0
 
LVL 3

Expert Comment

by:KhollAD
ID: 1524724
try the code below :

Option Explicit

Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

Private Type PROCESSENTRY32
   dwSize As Long
   cntUsage As Long
   th32ProcessID As Long
   th32DefaultHeapID As Long
   th32ModuleID As Long
   cntThreads As Long
   th32ParentProcessID As Long
   pcPriClassBase As Long
   dwFlags As Long
   szExeFile As String * 260
End Type

Private Const TH32CS_SNAPPROCESS = &H2&
Private Const hNull = 0

Private Sub Command1_Click()

    If ExeRunning("Sum.exe") Then
        MsgBox "Running"
    Else
        MsgBox "Not Running"
    End If

End Sub

Private Function ExeRunning(ByVal ExeFind As String) As Boolean

    Dim hProc As Long, ExeName As String
    Dim lRet As Long, Proc As PROCESSENTRY32
   
    hProc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
   
    ExeRunning = False
   
    If hProc = 0 Then
        Exit Function
    End If
   
    Proc.dwSize = Len(Proc)
    lRet = Process32First(hProc, Proc)
   
    Do While lRet
   
        ExeName = Left(Proc.szExeFile, Len(Proc.szExeFile) - 1)
        If InStr(1, UCase(Trim(ExeName)), UCase(Trim(ExeFind))) Then
            ExeRunning = True
            Exit Function
        End If
       
        lRet = Process32Next(hProc, Proc)
   
    Loop

End Function

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 9

Expert Comment

by:Dalin
ID: 1524725
Welcome back, mrmick.
0
 
LVL 8

Expert Comment

by:mrmick
ID: 1524726
Wow, I must say... that's a new trick for me.  I learn something new every day.

Thanks KhollAD

jfunderb, although my answer may satisfy your needs (or I wouldn't have responded), please REJECT my suggested answer because KhollAD has perfectly answered the question you asked and deserves credit for this one.  I learned a new trick too.  Thanks.


0
 

Author Comment

by:jfunderb
ID: 1524727
KhollAD,

I tried your code but got a 'Run-time error 453 - Can't find DLL entry point CreateToolhelp32Snapshot in kernel32'.  Am I missing something?  I'm running NT 4.0 SP5.

Thanks,
Jacob


0
 
LVL 1

Expert Comment

by:alex1234
ID: 1524728
KhollID's answer works only for WIN95, that is why you are getting the error.

0
 
LVL 1

Expert Comment

by:alex1234
ID: 1524729
jfunderb,

you can use PSAPI.DLL for the things similar to what KhollID suggested and it will work under NT4. Look in MSDN for this DLL API.

0
 
LVL 3

Expert Comment

by:KhollAD
ID: 1524730
thanks mrmick !!

jfunderb, sorry. In the NT you can use the PSAPI functions from PSAPI.DLL

if you don't have this file, you can get from :
(Visual Studio CD-ROM \Tools\Unsupprt\Wsview\winnt\Psapi.dll)

- copy to \winnt\system32
- you can add in your Install package.

try the code below :


Option Explicit

Private Declare Function CloseHandle Lib "Kernel32.dll" _
   (ByVal Handle As Long) As Long

Private Declare Function OpenProcess Lib "Kernel32.dll" _
  (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, _
      ByVal dwProcId As Long) As Long

Private Declare Function EnumProcesses Lib "psapi.dll" _
   (ByRef lpidProcess As Long, ByVal cb As Long, _
      ByRef cbNeeded As Long) As Long

Private Declare Function GetModuleFileNameExA Lib "psapi.dll" _
   (ByVal hProcess As Long, ByVal hModule As Long, _
      ByVal ModuleName As String, ByVal nSize As Long) As Long

Private Declare Function EnumProcessModules Lib "psapi.dll" _
   (ByVal hProcess As Long, ByRef lphModule As Long, _
      ByVal cb As Long, ByRef cbNeeded As Long) As Long


Private Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_READ = 16
Private Const MAX_PATH = 260
         

Private Sub Command1_Click()

If ExeRunning("Sum.Exe") Then
    MsgBox "Running"
Else
    MsgBox "Not Running"
End If


End Sub

Private Function ExeRunning(ByVal ExeName As String) As Boolean

   Dim hProcess As Long
   Dim cb As Long
   Dim cbNeeded As Long
   Dim NumElements As Long
   Dim ProcessIDs() As Long
   Dim cbNeeded2 As Long
   Dim NumElements2 As Long
   Dim Modules(1 To 200) As Long
   Dim lRet As Long
   Dim ModuleName As String
   Dim nSize As Long
   Dim i As Long
   
   ExeRunning = False
   
   'Get the array containing the process id's for each process object
   cb = 8
   cbNeeded = 96
   Do While cb <= cbNeeded
      cb = cb * 2
      ReDim ProcessIDs(cb / 4) As Long
      lRet = EnumProcesses(ProcessIDs(1), cb, cbNeeded)
   Loop
   NumElements = cbNeeded / 4

   For i = 1 To NumElements
      'Get a handle to the Process
      hProcess = OpenProcess(PROCESS_QUERY_INFORMATION _
         Or PROCESS_VM_READ, 0, ProcessIDs(i))
      'Got a Process handle
      If hProcess <> 0 Then
          'Get an array of the module handles for the specified
          'process
          lRet = EnumProcessModules(hProcess, Modules(1), 200, _
                                       cbNeeded2)
          'If the Module Array is retrieved, Get the ModuleFileName
          If lRet <> 0 Then
             ModuleName = Space(MAX_PATH)
             nSize = 500
             lRet = GetModuleFileNameExA(hProcess, Modules(1), _
                             ModuleName, nSize)
             If InStr(1, UCase(Trim(ModuleName)), UCase(Trim(ExeName))) <> 0 Then
                ExeRunning = True
             End If
             
          End If
      End If
    'Close the handle to the process
   lRet = CloseHandle(hProcess)
   Next

End Function

0
 

Author Comment

by:jfunderb
ID: 1524731
Thanks,

This will get the job done.
0
 
LVL 4

Expert Comment

by:wylliker
ID: 1524732
Also, to add to what you have been given ...

Since you said you want to wait in a loop for the process to end, you can avoid killing CPU cycles in a loop by adding the following:

Public Const INFINITE = &HFFFF      
Public Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long


Once you have found the process, you have the handle to it,

hProcess

at the top of the function, add

Dim hProcessToWaitFor  as long
Dim RetVal as long

Where the code in KhollAd's example above sets
 ExeRunning = True

add

 hProcessTo WaitFor = hProcess.

After the loop in the code above,
simply add

  if ExeRunning then
     RetVal =  WaitForSingleObject ( hProcessToWaitFor, INFINITE)
  end if

The WaitForSingleObject API will wait until the process handle is signaled - this will occur when the process ends.
When you are waiting for this to happen, Windows will pull your application so it won't get scheduled and use any CPU cycles until the other process has ended. Once that happens, your application will come alive again.
















0
 
LVL 1

Accepted Solution

by:
SiriusP earned 200 total points
ID: 1524733
Public Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Dim window As Long
window = FindWindow(vbNullString, "title")

you'll have to use the title
if you don't want classes
0
 

Author Comment

by:jfunderb
ID: 1524734
wylliker,

I added the WaitForSingleObject function. (Thanks exactly what I needed) But it doesn't seem wait for the process to end.  The function returns a value of -1, if that helps.
0
 
LVL 4

Expert Comment

by:wylliker
ID: 1524735
Just to make sure ...

In KhollAD code you add right here


If InStr(1, UCase(Trim(ModuleName)), UCase(Trim(ExeName))) <> 0 Then
   ExeRunning = True
   hProcessToWaitFor = hProcess
End If

Just before End Function but after the next statement
you add

if ExeRunning then
   RetVal =  WaitForSingleObject(hProcessToWaitFor, INFINITE)
end if

Under NT you have to have the SYNCHRONIZE access right in the Open Process call.  It may easier to use PROCESS_ALL_ACCESS, which is

Public Const PROCESS_ALL_ACCESS = &H1F0FFF

So you could replace the PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ parameter with PROCESS_ALL_ACCESS in the OpenProcess call.


Another way is
Public Const PROCESS_SYNCHRONIZE = &H100000

and then  PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ Or PROCESS_SYNCHRONIZE



Let me know how this turns out for you.












0
 

Author Comment

by:jfunderb
ID: 1524736
wylliker,

Yes, I added the code just as you have above.  I tried both of the PROCESS_ALL_ACCESS and the PROCESS_SYNCHRONIZE and neither of the worked.  Any suggestions?
0
 
LVL 4

Expert Comment

by:wylliker
ID: 1524737
-1 is returned (WAIT_FAILED).

The reason I suggested the PROCESS_ALL_ACCESS  and the PROCESS_SYNCHRONIZE is that NT process security has to be dealt with.

Do you know if the application you want to wait for is running in the same security context, ie. the application is not impersonating a different user than your application or requires admin rights to access the process handle?

Anybody else want to step up here and see if there is a way to use WaitForSingleObject

I won't be able to look at this again until over the weekend.





0
 

Author Comment

by:jfunderb
ID: 1524738
Right now I am logged into NT as a user with Administrator rights and for testing purposes I just using calc.exe as the program that I'm checking for.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction While answering a recent question (http://www.experts-exchange.com/Q_27402310.html) in the VB classic zone, I wrote some VB code in the (Office) VBA environment, rather than fire up my older PC.  I didn't post completely correct code o…
If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
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

705 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