【问题标题】:Process monitor / dispatcher in VB6VB6 中的进程监视器/调度程序
【发布时间】:2011-09-17 02:46:57
【问题描述】:

我需要在 VB6 中编写一个小应用程序来运行另一个 VB6 应用程序的实例并密切关注正在运行的进程,但我不知道如何在 VB6 中获取进程信息。我可以使用tasklist 实用程序查看我需要的一些内容,但我真的不知道如何创建进程(如果可能,指定进程或应用程序名称)以及从操作系统获取有关进程的信息。

此应用程序将在 Windows XP 机器上运行。

有人知道这类事情的入门教程或有用的网页吗?

【问题讨论】:

    标签: vb6 windows-xp


    【解决方案1】:

    您可以使用许多 Windows API 函数来执行此操作。我将从查看EnumProcesses (VB6 example and declaration here) 开始,它可用于收集有关所有正在运行的进程的信息。您也可以使用OpenProcess 开始向 Windows 询问特定进程 (another VB6 example)。

    还有一个fairly nice example on MSDN

    当然,还有 CreateProcess (AllApi link) 或 ShellExecute (AllApi) 用于生成进程 - 前者让您可以更好地控制进程的创建,而后者更简单打电话。

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

    另一种可能的方法是使用WMI (some useful snippets to adapt)。

    最后,这里有一些教程向您展示如何操作(不过我建议您自己先尝试一下:):

    以下是一些相关问题,尽管您在发帖前搜索此网站时可能已经看到它们:

    【讨论】:

      【解决方案2】:

      您无需为了获得您生成的子进程的句柄而对进程进行探索。 VB6 Shell() 函数返回一个进程ID,您可以使用它来调用OpenProcessCreateProcess 直接给你句柄。

      好的,这里是一个在 VB6 中生成和监视程序的超级精简示例。该示例被编码为启动并重复重新启动命令 shell 的 3 个副本(简单的示例子程序)。它还被编写为在终止时杀死任何正在运行的孩子,并且在大多数情况下有更好的替代方案可供使用。见A Safer Alternative to TerminateProcess()

      此演示还报告退出的每个进程的退出代码。您可以输入exit 1234 或类似的名称来查看此操作。

      要创建演示,请使用表单打开一个新的 VB6 项目。添加一个多行 TextBox Text1 和一个 Timer Timer1(用于轮询孩子完成)。将此代码粘贴到表单中:

      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
      

      希望这有助于回答这个问题。

      【讨论】:

      • 所以 CreateProcess 创建了一个子进程,那么,不是一个独立的?如果监视器/调度程序一团糟,我希望这些进程能够继续运行。
      • Windows 中的进程族链接通常相当薄弱。即使父进程终止,子进程仍将继续运行。
      • 呃,上面的评论是在谈论 CreateProcess() 或 VB 的 Shell() 的一般用途。我添加的代码示例在退出时明确地杀死了它的孩子。
      【解决方案3】:

      更简单的东西会使用套接字。

      启动您的应用服务器并在您的客户端上实现与您的服务器的通信。有了它,您将提供相互通信。

      我说。因为我不是你尝试做的事

      抱歉,仅当您的客户在内部完成时才适用,因为您可以选择添加更改

      【讨论】:

        【解决方案4】:

        既然你说其他应用程序是**也是VB6**,那么将其他应用程序制作成ActiveX exe会更容易。然后,您可以直接从您的第一个应用程序获取对另一个应用程序中对象的引用。 COM 为您解决一切。

        【讨论】:

        • 这项技术当然有它的应用,我个人建议将它作为一种可能性,用于某些类型的新工作。但是,如果子程序不是您编写的,它也无济于事,即便如此,它也可能需要进行相当多的重写。它还需要进程外 COM 注册,这在许多情况下可能是一个缺点。
        猜你喜欢
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 2017-07-21
        • 1970-01-01
        • 2012-04-23
        • 2015-07-21
        • 2016-06-21
        相关资源
        最近更新 更多