我在VB中调用一个C语言的编译器!
调用一个程序生成一个文件。
下一步要调用另一个程序根据生成的文件生成其他的文件!
第一个DOS程序没有执行完毕就执行第二个程序!
结果出错!
怎么判断DOS程序执行完毕!
我判断文件存在不行!有的文件没有写完就被执行!怎么判断呢?
我的方法怎么不行呢?
Public Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Global Const INFINITE = -1&
Global Const SYNCHRONIZE = &H100000调用程序
a = Shell(程序名, 0)
pHandle = OpenProcess(SYNCHRONIZE, False, a)
ret = WaitForSingleObject(pHandle, INFINITE)
ret = CloseHandle(pHandle)
‘下一步 程序
但是还是没有执行完就执行下一步程序!
帮忙!
调用一个程序生成一个文件。
下一步要调用另一个程序根据生成的文件生成其他的文件!
第一个DOS程序没有执行完毕就执行第二个程序!
结果出错!
怎么判断DOS程序执行完毕!
我判断文件存在不行!有的文件没有写完就被执行!怎么判断呢?
我的方法怎么不行呢?
Public Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Global Const INFINITE = -1&
Global Const SYNCHRONIZE = &H100000调用程序
a = Shell(程序名, 0)
pHandle = OpenProcess(SYNCHRONIZE, False, a)
ret = WaitForSingleObject(pHandle, INFINITE)
ret = CloseHandle(pHandle)
‘下一步 程序
但是还是没有执行完就执行下一步程序!
帮忙!
另外,如果您的shell所Create的程式,有视窗且为立刻Focus者,可另外用以下的方式Dim pid As Long Dim hwnd5 As Long pid = Shell("c:\tools\spe3\pe2.exe", vbNormalFocus) hwnd5 = GetForegroundWindow() isDone = False Do While IsWindow(hwnd5) DoEvents Loop isDone = True
而如何强迫shell所Create的process结束呢,那便是Dim aa As Long If hProcess <> 0 Then aa = TerminateProcess(hProcess, 3838) End If
Debug.Print ExitCode
DoEvents
Loop While ExitCode = STILL_ALIVE
Debug.print ExitCode 而执行了 TerminateProcess(hProcess, 3838)那会看到ExitCode = 3838。然而,这个方式在win95没问题,在NT中,可能您要在OpenProcess()的第一个参数要更改成 PROCESS_QUERY_INFORMATION Or PROCESS_TERMINATE 这样才能Work。不过良心的建议,非到最後关头,不要使用TerminateProcess(),因不正常的结束,往往许多程式结束前所要做的事都没有做,可能造成Resource的浪费,甚者,下次再执行某些程式时会有问题,例如:本人常使用MS-dos Shell Link 的方式执行一程式,透过Com port与大电脑的联结,如果Ms-dos Shell Link 不正常结束,下次再想Link时,会发现too Many Opens,这便是一例。 另外,有人使用Shell来执行.bat档,即:
pid = Shell("c:\aa.bat", vbNormalFocus) 可是却遇上aa.bat结束了,但ms-dos的Window却仍活着,那可以用以下的方式来做pid = Shell("c:\command.com /c c:\aa.bat", vbNormalFocus) 那是执行Command.com,而Command.com指定执行c:\aa.bat 而且结束时自动Close 所有程式如下: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 Private Declare Function GetExitCodeProcess Lib "kernel32"(ByVal hProcess As Long, lpExitCode As Long) As Long Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long Private Declare Function GetForegroundWindow Lib "user32" () As Long Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long Const PROCESS_QUERY_INFORMATION = &H400 Const STILL_ALIVE = &H103 Const INFINITE = &HFFFF Private ExitCode As Long
Private hProcess As Long
Private isDone As Long Private Sub Command1_Click()
Dim pid As Long
pid = Shell("C:\tools\spe3\pe2.exe", vbNormalFocus)
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
isDone = False
Do
Call GetExitCodeProcess(hProcess, ExitCode)
Debug.Print ExitCode
DoEvents
Loop While ExitCode = STILL_ALIVE
Call CloseHandle(hProcess)
isDone = True
End Sub Private Sub Command2_Click() Dim pid As Long Dim ExitEvent As Long pid = Shell("C:\tools\spe3\pe2.exe", vbNormalFocus) hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid) ExitEvent = WaitForSingleObject(hProcess, INFINITE) Call CloseHandle(hProcess) End Sub Private Sub Command3_Click()
If hProcess <> 0 Then
TerminateProcessh Process, 3838
End If
End Sub Private Sub Command4_Click() Dim pid As Long Dim hwnd5 As Long pid = Shell("c:\tools\spe3\pe2.exe", vbNormalFocus) hwnd5 = GetForegroundWindow()
isDone = False
Do While IsWindow(hwnd5)
DoEvents
Loop
isDone = True
End Sub Private Sub Command5_Click()
Shell "c:\command.com /c c:\aa.bat", vbNormalFocus ' vbHide)
End Sub
Shell & Wait 的程序怎么写?
希望某一 VB 程序利用 Shell 执行某一个外部程序(假设是 notepad.exe)之后,
就一直等到此一程序结束执行时, 才回到 VB 程序继续执行, 该怎么办到呢?
当我们调用 Shell 时, 会传回一个数值, 此一数值称为 Process Id, 利用此
一 Process Id, 我们可以调用 OpenProcess API 取得 Process Handle, 然后
再利用 Process Handle 调用 WaitForSingleObject, 即可等待被 Shell 执行的
程序执行完毕, 才继续向下执行。细节如下:
1. API 的声明:
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF
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
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal
hHandle As Long, ByVal dwMilliseconds As Long) As Long
注:如果以上的声明放在「一般模块」底下, 应将 Declare 之前的 Private 保
留字去掉, 并且在 Const 之前加上 Public 保留字。
2. 程序范例:(以执行 Notepad 程序为例)
Dim pId As Long, pHnd As Long ' 分别声明 Process Id 及 Process Handle 变
数
pId = Shell("Notepad", vbNormalFocus) ' Shell 传回 Process Id
pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' 取得 Process Handle
If pHnd <> 0 Then
Call WaitForSingleObject(pHnd, INFINITE) ' 无限等待,直到程序结束
Call CloseHandle(pHnd)
End If
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF
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
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Sub Command1_Click()
'(以执行 Notepad 程序为例)
Dim pId As Long, pHnd As Long ' 分别声明 Process Id 及 Process Handle
pId = Shell("Notepad", vbNormalFocus) ' Shell 传回 Process Id
pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' 取得 Process Handle
If pHnd <> 0 Then
Call WaitForSingleObject(pHnd, INFINITE) ' 无限等待,直到程序结束
Call CloseHandle(pHnd)
MsgBox "Notepad已关闭"
End IfEnd Sub
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As LongPrivate Const SYNCHRONIZE = &H100000
Private Const INFINITE = &HFFFF ' Infinite timeout
Private Const WAIT_TIMEOUT = &H102&Public Function ShellForWait(sAppName As String, Optional ByVal lShowWindow As VbAppWinStyle = vbMinimizedFocus, Optional ByVal lWaitTime As Long = 0) As Boolean
Dim lID As Long, lHnd As Long, lRet As Long
On Error Resume Next
lID = Shell(sAppName, lShowWindow)
If lID > 0 Then
lHnd = OpenProcess(SYNCHRONIZE, 0, lID)
If lHnd <> 0 Then
Do
lRet = WaitForSingleObject(lHnd, lWaitTime)
DoEvents
Loop While lRet = WAIT_TIMEOUT
CloseHandle lHnd
ShellForWait = True
Else
ShellForWait = False
End If
Else
ShellForWait = False
End If
End FunctionSub Main()
ShellForWait "cmd.exe ", , &HFFFF
End Sub
Public Const SYNCHRONIZE = &H100000
Public Const INFINITE = &HFFFF
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
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" Alias "TerminateProcess" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
'打开
Dim pId As Long, pHnd As Long
pId = Shell("Command.com", vbNormalFocus)
pHnd = OpenProcess(SYNCHRONIZE, 0, pId)
'关闭
Call TerminateProcess( pHnd, 0 )
Call CloseHandle( pHnd )
如下方法可取!!!!
----------------------------------------------------------------------------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
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As LongPrivate Const SYNCHRONIZE = &H100000
Private Const INFINITE = &HFFFF ' Infinite timeout
Private Const WAIT_TIMEOUT = &H102&Public Function ShellForWait(sAppName As String, Optional ByVal lShowWindow As VbAppWinStyle = vbMinimizedFocus, Optional ByVal lWaitTime As Long = 0) As Boolean
Dim lID As Long, lHnd As Long, lRet As Long
On Error Resume Next
lID = Shell(sAppName, lShowWindow)
If lID > 0 Then
lHnd = OpenProcess(SYNCHRONIZE, 0, lID)
If lHnd <> 0 Then
Do
lRet = WaitForSingleObject(lHnd, lWaitTime)
DoEvents
Loop While lRet = WAIT_TIMEOUT
CloseHandle lHnd
ShellForWait = True
Else
ShellForWait = False
End If
Else
ShellForWait = False
End If
End FunctionSub Main()
ShellForWait "cmd.exe ", , &HFFFF
End Sub