跳转到内容

Visual Basic/外部进程

来自维基教科书,自由的教科书

通常情况下,已经存在一个程序可以完成某些工作,因此与其在 Visual Basic 中重新编写该程序,不如从 Visual Basic 中运行现有程序更有效。这对于命令行程序或任何语言编写的脚本非常有效。

一般方案是创建一个包含命令行的字符串,调用一个函数来运行它,然后等待命令完成。可以进行许多改进,包括各种向新进程发送数据、从中读取结果、暂停它、设置其优先级等的方法。

Shell 函数

[编辑 | 编辑源代码]

运行外部程序的最简单方法是执行类似以下操作

Shell "cmd /c dir %temp%"

Shell 是 Visual Basic 中的内置函数,它执行命令行并返回对该进程的句柄Shell 接受一个可选参数,该参数控制新进程的窗口样式(最大化、正常、隐藏等)。

不幸的是,像这样运行另一个程序并不会让你对正在发生的事情有太多控制。特别是,没有明显的方法可以知道程序是否已完成其工作。

幸运的是,Shell 实际上比启动程序做得更多。它还返回进程 ID。这是任务管理器显示的数字,可用于检查进程的状态。不幸的是,正如 Visual Basic 和 Windows 的许多情况下那样,没有内置函数,甚至没有单个 API 函数可以直接使用它。因此,我们必须编写更多代码。首先,我们必须声明一些 API 函数和常量

  Option Explicit
  
  Const SYNCHRONIZE = &H100000
  Const INFINITE = &HFFFF    'Wait forever
  Const WAIT_OBJECT_0 = 0    'The state of the specified object is signaled.
  Const WAIT_TIMEOUT = &H102 'The time-out interval elapsed, and the object’s state is nonsignaled.
  
  Private Declare Function OpenProcess Lib "kernel32" _
          (ByVal dwDesiredAccess As Long, _
           ByVal bInheritHandle As Long, _
           ByVal dwProcessId As Long) _
          As Long
  Private Declare Function WaitForSingleObject Lib "kernel32" _
          (ByVal hHandle As Long, _
           ByVal dwMilliseconds As Long) _
          As Long
  Private Declare Function CloseHandle Lib "kernel32" _
          (ByVal hObject As Long) _
          As Long
  
  Dim ProcessID As Long
  Dim hProcess As Long

以下是一个执行命令并等待其完成的函数示例

  Function ShellWait(CommandLine As String, _
                     TimeOut As Long, _
                     WindowState As VbAppWinStyle) As Boolean
    
    Dim ProcessID As Long
    Dim hProcess As Long
    
    ProcessID = Shell(CommandLine,WindowState)
    If ProcessID <> 0 Then
      'non-zero (True) so Shell worked
      ' Get a process handle for the PID (Wait takes a handle)
      hProcess = OpenProcess(SYNCHRONIZE, False, ProcessID)
      If hProcess <> 0 Then
        ' Got process handle
        ' Wait until process finishes before going on
        If WaitForSingleObject(hProcess, TimeOut) = WAIT_OBJECT_0 Then
          ShellWait = True
        Else
          ShellWait = False
        End If
      Else
        'Failed to get process handle.
        'Perhaps the process terminated very quickly
        'or it might not really have executed at all even though Windows
        ' started a process.
        ShellWait = False
      End If
    Else
      ' PID zero (False) so Shell failed
      ShellWait = False
    End If
  End Function

像这样调用它

  If ShellWait("calc.exe") then
    MsgBox "Success :-)"
  Else
    MsgBox "Failure :-("
  End If
  • 修改 ShellWait 示例函数,以便调用者可以区分启动进程失败和超时。
  • 建议一个原因,说明为什么这可能是个好主意。


前一个: Windows_API 目录 下一个: 面向对象编程
华夏公益教科书