Visual Basic 6 function "FindProcess"

Go back

Below you'll find the source for the Visual Basic 6 function FindProcess.

Attribute VB_Name = "modFindProcess"
' These functions are downloaded from:
' http://www.stefanthoolen.nl/archive/vb6-functions/
' 
' You may freely distribute this file but please leave all comments, including this one, in it.
' 
' @Author Stefan Thoolen <mail@stefanthoolen.nl>

Option Explicit

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

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

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

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal Hwnd As Long, lpdwProcessId As Long) As Long

Private Declare Function GetWindow Lib "user32" (ByVal Hwnd As Long, ByVal wCmd As Long) As Long

Private Declare Function GetParent Lib "user32" (ByVal Hwnd As Long) As Long

Private Declare Function FindWindowA Lib "user32" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long

Private Declare Function GetWindowTextA Lib "user32" (ByVal Hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function GetWindowTextLengthA Lib "user32" (ByVal Hwnd As Long) As Long

Private Const TH32CS_SNAPPROCESS As Long = &H2

Private Const GW_HWNDNEXT = 2

' Must be defined after WindowEntry
' If not, you get "Forward reference to user-defined type"
Public Type ProcessEntry
    processID As Long
    ExeFile As String
    Windows() As WindowEntry
End Type

Private Type PROCESSENTRY32
    dwSize              As Long ' The length in bytes of the structure
    cntUsage            As Long ' The number of references to the process
    th32ProcessID       As Long ' Identifier of the process
    th32DefaultHeapID   As Long ' Identifier of the default heap for the process
    th32ModuleID        As Long ' Identifier of the process's module
    cntThreads          As Long ' The number of threads started by the program
    th32ParentProcessID As Long ' The identifier of the process that created this process
    pcPriClassBase      As Long ' The base priority by any threads created by this class
    dwFlags             As Long
    szExeFile           As String * 260 ' The filename of the executable file for the process
End Type

' Own types to return information
Public Type WindowEntry
    Hwnd As Long
    Caption As String
End Type


''
' Gets a window caption
' @param    Long    Hwnd        The window handler
' @return   String              The caption of the window
' @author   Stefan Thoolen <mail@stefanthoolen.nl>
Public Function GetWindowCaption(Hwnd As Long) As String
    Dim l As Long, s As String
    
    l = GetWindowTextLengthA(Hwnd) + 1
    s = String(l, 0)
    GetWindowTextA Hwnd, s, l
    
    GetWindowCaption = Left(s, InStr(s, vbNullChar) - 1)
End Function

''
' Returns all kind of Window-information of a process
' Example:
'    Dim we() As WindowEntry
'    GetProcessWindows pid, we
'
' @param    Long    processID       The process ID
' @param    WindowEntry arr         An entry containing all information of the window
' @return   Void
' @author   Stefan Thoolen <mail@stefanthoolen.nl>
Public Sub GetProcessWindows(processID As Long, ByRef arr() As WindowEntry)
    Dim tmp_hwnd As Long, hwnd_cnt As Integer: hwnd_cnt = -1
    Dim tmp_pid As Long
    Dim tmp_thread_id As Long
    tmp_hwnd = FindWindowA(ByVal 0&, ByVal 0&)
    Do While tmp_hwnd <> 0
        If GetParent(tmp_hwnd) = 0 Then
            tmp_thread_id = GetWindowThreadProcessId(tmp_hwnd, tmp_pid)
            If tmp_pid = processID Then
                hwnd_cnt = hwnd_cnt + 1
                ReDim Preserve arr(0 To hwnd_cnt)
                arr(hwnd_cnt).Hwnd = tmp_hwnd
                arr(hwnd_cnt).Caption = GetWindowCaption(tmp_hwnd)
            End If
        End If
        tmp_hwnd = GetWindow(tmp_hwnd, GW_HWNDNEXT)
    Loop
End Sub

''
' Returns a list of all processes
' Example:
'    Dim pl() As ProcessEntry
'    GetProcessList pl
'
' @param    ProcessEntry pl     An array containing a lot of Process Entries
' @return   Void
' @author   Stefan Thoolen <mail@stefanthoolen.nl>
Public Sub GetProcessList(ByRef pl() As ProcessEntry)
    Dim retval() As ProcessEntry, row As ProcessEntry, cnt As Integer
    Dim snap As Long, l As Long, hWnds() As WindowEntry
    Dim processInfo As PROCESSENTRY32
    
    ' At default an empty array
    cnt = -1: pl = retval
    
    ' Also a default value, this is always the same
    processInfo.dwSize = Len(processInfo)
    
    ' A snapshot of the current list
    snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    If snap = -1 Then Exit Sub
    
    ' Gets the first item
    l = Process32First(snap, processInfo)
    
    Do While l <> 0
        ' Adds the item to the new array
        cnt = cnt + 1
        ReDim Preserve retval(0 To cnt)
        GetProcessWindows processInfo.th32ProcessID, hWnds
        row.processID = processInfo.th32ProcessID
        row.ExeFile = Left(processInfo.szExeFile, InStr(processInfo.szExeFile, vbNullChar) - 1)
        row.Windows = hWnds
        retval(cnt) = row
        ' Gets the next item
        l = Process32Next(snap, processInfo)
    Loop
    
    CloseHandle snap
    
    pl = retval
End Sub

''
' Searches for a process by it's executable name
' Example:
'    Dim pe() As ProcessEntry
'    If FindProcess("notepad.exe", pe) Then MsgBox pe(0).Windows(0).Caption
'
' @param    String        exename      The name of the executable to search for
' @param    ProcessEntry  processes    An array witch will be filled with all process ids which match with exename
' @return   boolean                    True if one or more processes matches, false otherwise
' @author   Stefan Thoolen <mail@stefanthoolen.nl>
Public Function FindProcess(ByVal exename As String, ByRef processes() As ProcessEntry) As Boolean
    Dim pl() As ProcessEntry, i As Integer
    Dim retval() As ProcessEntry, cnt As Integer
    GetProcessList pl
    For i = LBound(pl) To UBound(pl)
        If InStr(LCase(pl(i).ExeFile), LCase(exename)) > 0 Then
            ReDim Preserve retval(0 To cnt)
            retval(cnt) = pl(i)
            cnt = cnt + 1
        End If
    Next i
    processes = retval
    If cnt > 0 Then FindProcess = True
End Function