我提供个另类的简单方案:Shell函数返回的是目标进程的PID,而使用GetProcessVersion函数传入PID后能得到目标进程的版本信息.一旦PID无效,即目标进程退出,GetProcessVersion函数将返回0.利用这个特点,以下模块就能实现同步执行进程http://www.m5home.com/bbs/thread-1016-1-1.htmlOption Explicit '************************************************************************* '**模 块 名:ModShellEx '**说 明:增强SHELL函数 '**创 建 人:马大哈 '**描 述:紫水晶工作室 http://www.m5home.com/ '**日 期:2007年4月24日 '**版 本:V1.0 '*************************************************************************Private Declare Function GetProcessVersion Lib "kernel32" (ByVal ProcessId As Long) As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)Public Function ShellEx(ByVal FileName As String, Optional ByVal WindowStyle As VbAppWinStyle = vbNormalFocus, Optional ByVal DelayTime As Long = -1) '与SHELL函数一样的参数,不过是阻塞执行.(同步) 'FileName - 目标文件名 'WindowStyle - 程序运行时窗口的样式 'DelayTime - 等待的时间,单位为ms '备注: ' DelayTime设置为-1时表示一直等待,直到目标程序运行结束 Dim I As Long, J As Long
I = Shell(FileName, WindowStyle) Do If GetProcessVersion(I) = 0 Then Exit Do Sleep 10 J = J + 1 If DelayTime <> -1 And J > DelayTime \ 10 Then Exit Do Loop End Function
实现这种等待的方法至少有两种: 第一种方法是利用 Windows API 的 OpenProcess 和 CloseHandle 函数来实现对被调用软件的检测: 1) 在VB中新建一个标准EXE工程; 2) 在Form1中声明OpenProcess和 CloseHandle 这两个Windows API 函数; Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long 3) 然后编写下面的函数: Function IsRunning(ByVal ProgramID) As Boolean ' 传入进程标识ID Dim hProgram As Long '被检测的程序进程句柄 hProgram = OpenProcess(0, False, ProgramID) If Not hProgram = 0 Then IsRunning = True Else IsRunning = False End If CloseHandle hProgram End Function 4) 在Form_Click()中加入代码:
Sub Form_Click() Dim X Me.Caption = "开始运行" X = Shell("NotePad.EXE", 1) While IsRunning(X) DoEvents Wend Me.Caption = "结束运行" End Sub 第二种方法是利用Win32 API的CreateProcess函数和WaitForSingleObject函数来进行这一工作。它的原理比较复杂,在此只介绍如何使用。首先建立一个模块(module),然后输入以下语句: Option Explicit
Type STARTUPINFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessID As Long dwThreadID As Long End Type Global Const NORMAL_PRIORITY_CLASS = &H20& Global Const INFINITE = -1& Declare Function CloseHandle Lib "kernel32" (hObject As Long) As Boolean Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Declare Function CreateProcessA Lib "kernel32" ( _ ByVal lpApplicationName As Long, _ ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal _ lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal _ dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal _ lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, _ lpProcessInformation As PROCESS_INFORMATION) As Long
Public Sub ShellAndWait(cmdline$) Dim NameOfProc As PROCESS_INFORMATION Dim NameStart As STARTUPINFO Dim X As Long
NameStart.cb = Len(NameStart) X = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, _ 0&, 0&, NameStart, NameOfProc) X = WaitForSingleObject(NameOfProc.hProcess, INFINITE) X = CloseHandle(NameOfProc.hProcess) End Sub 建立一个窗体,并放一个命令按钮(Command1)在其上。在Command1_Click事件中输入以下内容: Private Sub Command1_Click() Dim AppToLaunch As String
AppToLaunch = "c:\win95\notepad.exe" ShellAndWait AppToLaunch End Sub 运行该程序,按下 Command1,就会调用 NotePad,在 NotePad 运行完毕之前,VB程序不会继续执行。你可以在程序中使用 ShellAndWait 来代替Shell命令。
'*************************************************************************
'**模 块 名:ModShellEx
'**说 明:增强SHELL函数
'**创 建 人:马大哈
'**描 述:紫水晶工作室 http://www.m5home.com/
'**日 期:2007年4月24日
'**版 本:V1.0
'*************************************************************************Private Declare Function GetProcessVersion Lib "kernel32" (ByVal ProcessId As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)Public Function ShellEx(ByVal FileName As String, Optional ByVal WindowStyle As VbAppWinStyle = vbNormalFocus, Optional ByVal DelayTime As Long = -1)
'与SHELL函数一样的参数,不过是阻塞执行.(同步)
'FileName - 目标文件名
'WindowStyle - 程序运行时窗口的样式
'DelayTime - 等待的时间,单位为ms
'备注:
' DelayTime设置为-1时表示一直等待,直到目标程序运行结束
Dim I As Long, J As Long
I = Shell(FileName, WindowStyle)
Do
If GetProcessVersion(I) = 0 Then Exit Do
Sleep 10
J = J + 1
If DelayTime <> -1 And J > DelayTime \ 10 Then Exit Do
Loop
End Function
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long 3) 然后编写下面的函数: Function IsRunning(ByVal ProgramID) As Boolean ' 传入进程标识ID
Dim hProgram As Long '被检测的程序进程句柄
hProgram = OpenProcess(0, False, ProgramID)
If Not hProgram = 0 Then
IsRunning = True
Else
IsRunning = False
End If
CloseHandle hProgram
End Function 4) 在Form_Click()中加入代码:
Sub Form_Click()
Dim X
Me.Caption = "开始运行"
X = Shell("NotePad.EXE", 1)
While IsRunning(X)
DoEvents
Wend
Me.Caption = "结束运行"
End Sub 第二种方法是利用Win32 API的CreateProcess函数和WaitForSingleObject函数来进行这一工作。它的原理比较复杂,在此只介绍如何使用。首先建立一个模块(module),然后输入以下语句: Option Explicit
Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadID As Long
End Type Global Const NORMAL_PRIORITY_CLASS = &H20&
Global Const INFINITE = -1&
Declare Function CloseHandle Lib "kernel32" (hObject As Long) As Boolean
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Declare Function CreateProcessA Lib "kernel32" ( _
ByVal lpApplicationName As Long, _
ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal _
lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal _
dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal _
lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION) As Long
Public Sub ShellAndWait(cmdline$)
Dim NameOfProc As PROCESS_INFORMATION
Dim NameStart As STARTUPINFO
Dim X As Long
NameStart.cb = Len(NameStart)
X = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, _
0&, 0&, NameStart, NameOfProc)
X = WaitForSingleObject(NameOfProc.hProcess, INFINITE)
X = CloseHandle(NameOfProc.hProcess)
End Sub 建立一个窗体,并放一个命令按钮(Command1)在其上。在Command1_Click事件中输入以下内容: Private Sub Command1_Click()
Dim AppToLaunch As String
AppToLaunch = "c:\win95\notepad.exe"
ShellAndWait AppToLaunch
End Sub 运行该程序,按下 Command1,就会调用 NotePad,在 NotePad 运行完毕之前,VB程序不会继续执行。你可以在程序中使用 ShellAndWait 来代替Shell命令。