开发者

Process monitor / dispatcher in VB6

I need to write a little application in VB6 to run instances of another VB6 application and keep an eye on the running processes, but I don't have any idea how to get process information in VB6. I can see some of what I need with the tasklist utility but I don't really know how create processes (specifying the process or application name if possible) and fetching information about processes from the operating system.

This application is to run on a Windows XP machine.

Does anyone know of a get-you-started tutorial o开发者_运维知识库r helpful web page for this sort of thing?


There are numerous Windows API functions you can use to do this. I'd start with looking at EnumProcesses (VB6 example and declaration here) which can be used to gather information about all running processes. You can also use OpenProcess to start interrogating Windows about a particular process (another VB6 example).

There is also a fairly nice example on MSDN.

And of course, there is CreateProcess (AllApi link) or ShellExecute (AllApi) for spawning processes - the former gives you more control over the creation of the process, while the latter is a much simpler call.

There was another question posted about this a while back with some example code.

Another possible approach would be to use WMI (some useful snippets to adapt).

Finally, here are some tutorials that show you how to do it (I'd recommend trying it yourself first though :):

  • Getting Process Information using PSAPI
  • Another EnumProcesses/OpenProcess implementation
  • WMI-based demonstration

Here are some related questions although you probably already saw them when you searched this site before posting:

  • Monitoring processes to see if they've crashed in vb6
  • How can I execute a .bat file but wait until its done running before moving on?
  • How To Enumerate Processes From VB 6 on Win 2003?


Since you say the other application is ** also VB6**, it would be easier to make the other application into an ActiveX exe. Then you can get references to objects in the other application direct from your first application. COM solves it all for you.

  • Here's Microsoft's tutorial on the subject - you can download the code too.
  • Or here's another answer where I've written about this


You don't need to go spelunking for processes just to get a handle to child processes that you spawn. The VB6 Shell() function returns a Process ID you can use to call OpenProcess with. CreateProcess gives you the handle directly.

Ok, here is a super-stripped-down example of a program in VB6 to spawn and monitor programs. The example is coded to start and repeatedly restart 3 copies of the command shell (trivial sample child program). It is also written to kill any running children when it is terminated, and there are better alternatives to use in most cases. See A Safer Alternative to TerminateProcess().

This demo also reports back the exit code of each process that quits. You could enter exit 1234 or somesuch to see this in action.

To create the demo open a new VB6 Project with a Form. Add a multiline TextBox Text1 and a Timer Timer1 (which is used to poll the children for completion). Paste this code into the Form:

Option Explicit

Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_QUERY_INFORMATION = &H400&
Private Const PROCESS_TERMINATE = &H1&
Private Const WAIT_OBJECT_0 = 0
Private Const INVALID_HANDLE = -1
Private Const DEAD_HANDLE = -2

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

Private Declare Function GetExitCodeProcess Lib "kernel32" ( _
    ByVal hProcess As Long, _
    ByRef lpExitCode As Long) As Long

Private Declare Function OpenProcess Lib "kernel32" ( _
    ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Long, _
    ByVal dwProcessId As Long) As Long

Private Declare Function TerminateProcess Lib "kernel32" ( _
    ByVal hProcess As Long, _
    ByVal uExitCode As Long) As Long

Private Declare Function WaitForSingleObject Lib "kernel32" ( _
    ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) As Long

Private Tasks() As String
Private Handles() As Long

Private Sub Form_Load()
    Dim I As Integer

    'We'll run 3 copies of the command shell as an example.
    ReDim Tasks(2)
    ReDim Handles(2)
    For I = 0 To 2
        Tasks(I) = Environ$("COMSPEC") & " /k ""@ECHO I am #" & CStr(I) & """"
        Handles(I) = INVALID_HANDLE
    Next
    Timer1.Interval = 100
    Timer1.Enabled = True
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    Dim I As Integer

    Timer1.Enabled = False
    DoEvents
    For I = 0 To UBound(Tasks)
        If Handles(I) <> INVALID_HANDLE And Handles(I) <> DEAD_HANDLE Then
            TerminateProcess Handles(I), 666
            CloseHandle Handles(I)
            Handles(I) = DEAD_HANDLE
        End If
    Next
End Sub

Private Sub Timer1_Timer()
    Dim I As Integer
    Dim ExitCode As Long
    Dim Pid As Long

    Timer1.Enabled = False
    For I = 0 To UBound(Tasks)
        If Handles(I) <> INVALID_HANDLE Then
            If WaitForSingleObject(Handles(I), 0) = WAIT_OBJECT_0 Then
                If GetExitCodeProcess(Handles(I), ExitCode) <> 0 Then
                    Text1.SelText = "Task " & CStr(I) & " terminated, " _
                                  & "exit code: " & CStr(ExitCode) _
                                  & ", restarting task." _
                                  & vbNewLine
                Else
                    Text1.SelText = "Task " & CStr(I) & " terminated, " _
                                  & "failed to retrieve exit code, error " _
                                  & CStr(Err.LastDllError) _
                                  & ", restarting task." _
                                  & vbNewLine
                End If
                CloseHandle Handles(I)
                Handles(I) = INVALID_HANDLE
            End If
        End If
        If Handles(I) = INVALID_HANDLE Then
            Pid = Shell(Tasks(I), vbNormalFocus)
            If Pid <> 0 Then
                Handles(I) = OpenProcess(SYNCHRONIZE _
                                      Or PROCESS_QUERY_INFORMATION _
                                      Or PROCESS_TERMINATE, 0, Pid)
                If Handles(I) <> 0 Then
                    Text1.SelText = "Task " & CStr(I) & " started." _
                                  & vbNewLine
                Else
                    Text1.SelText = "Task " & CStr(I) _
                                  & ", failed to open child process." _
                                  & vbNewLine
                    Handles(I) = DEAD_HANDLE
                End If
            Else
                Text1.SelText = "Task " & CStr(I) _
                              & ", failed to Shell child process." _
                              & vbNewLine
                Handles(I) = DEAD_HANDLE
            End If
        End If
    Next
    Timer1.Enabled = True
End Sub

Hopefully this helps answer the question.


something more simple will use sockets.

Launch you app server and on your client implements the communication against your server. With that you will provide intercommunication.

well i say. because i dont be what you try do

Sorry it only apply if your clients are done in house i you have the option of added changes

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜