Friday, March 4, 2011

Monitoring processes to see if they've crashed in vb6

I've got a program that tends to crash quite often while I'm asleep and I need to keep it running. So I thought I might writeup a vb6 application that monitors the process list, if something disappears it will relaunch it. Anyone know of an easy way?

From stackoverflow
  • Use WMI.

    If you're stuck with VB6, search the web for WMI+VB6.
    Otherwise, interfacing c# and WMI is much easier.

  • I've used scheduled task (running at each 10 min), starting cmd file with next content:

    tasklist |find "myapp.exe" >nul || c:\mypath\myapp.exe

    You can execute such command file from VB6 Shell or just use Task Scheduler :)

    friol : That's a cheap solution, I like it.
  • I use a program that runs other programs. That way you can poll the process handle to see if the application is still running. If not you can launch it again. It does require API programming.

  • You could use EnumProcesses to list every process in the system at the moment you're running you could use this declaration to use it

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

    Prior using it you should define an array of Long to pass as an argument to EnumProcesses with enough space to read all processes ids. You could call EnumProcesses twice to discover how large that array should be. After the second call you could start looping through that array and opening the processes obtaining that way a handle which used appropriately can tell you the name of the process executable and comparing that data with the name of the executable you're searching you are done. Otherwise if what you're looking for is a DLL for example you could EnumProcessModules for that process handle searching for each running process for the dll you're looking for. the declaration of EnumProcessModules is this

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

    and the probable code you'd need would be something like this

    Option Explicit
    
    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 Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    
    Private Const PROCESS_ALL_ACCESS         As Long = &H1F0FFF
    
    Public Function IsModuleRunning(ByVal theModuleName As String) As Boolean
        Dim aProcessess(1 To 1024)  As Long ' up to 1024 processess?'
        Dim bytesNeeded             As Long
        Dim i                       As Long
        Dim nProcesses              As Long
        Dim hProcess                As Long
        Dim found                   As Boolean
    
        EnumProcesses aProcessess(1), UBound(aProcessess), bytesNeeded
        nProcesses = bytesNeeded / 4
        For i = 1 To nProcesses
    
            hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, aProcessess(i))
            If (hProcess) Then
                Dim hmodule(1 To 1024)  As Long ' no more than 1024 modules per process?'
                bytesNeeded = 0
                If EnumProcessModules(hProcess, hmodule(1), 1024 * 4, bytesNeeded) Then
                    Dim nModules    As Long
                    Dim j           As Long
                    Dim moduleName  As String
    
                    moduleName = Space(1024)   ' module name should have less than 1024 bytes'
    
                    nModules = bytesNeeded / 4
                    For j = 1 To nModules
                        Dim fileNameLen As Long
                        fileNameLen = GetModuleFileNameExA(hProcess, hmodule(j), moduleName, 1024)
                        moduleName = Left(moduleName, fileNameLen)
                        If Right(LCase(moduleName), Len(theModuleName)) = LCase(theModuleName) Then
                            found = True
                            Exit For
                        End If
                    Next
                End If
            End If
            CloseHandle hProcess
            If found Then Exit For
        Next
        IsModuleRunning = found
    End Function
    
    Private Sub Form_Load()
        MsgBox IsModuleRunning("explorer.exe")
    End Sub
    

    function code is a little long but calling it is a little function, you may use it if you want to test it a little :)

0 comments:

Post a Comment