VB 6: Как я могу выполнить файл .bat, но до тех пор, пока он не запустится?VB 6: Как я могу выполнить .bat-файл, но до его продолжения до его продолжения?
ответ
Вам нужно будет использовать вызовы API Win32 для ShellExecuteEx и WaitForSingleObject на дескрипторе процесса, возвращенном из ShellExecuteEx в структуре SHELLEXECUTEINFO. Это старый код, который я вытащил из проекта. Он работал на 100%, но я мог не включать все зависимости. Вы должны быть в состоянии изменить к вашим требованиям:
Type SHELLEXECUTEINFO
cbSize As Long
fMask As Long
hwnd As Long
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As String
nShow As Long
hInstApp As Long
' Optional fields'
lpIDList As Long
lpClass As String
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hProcess As Long
End Type
Public Declare Function ShellExecuteEx Lib "shell32.dll"
(lpExecInfo As SHELLEXECUTEINFO) As Long
Public Declare Function apiShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" _
(ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) _
As Long
Declare Function WaitForSingleObject Lib "kernel32"
(ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Const SEE_MASK_NOCLOSEPROCESS As Long = &H40
Public Const SEE_MASK_FLAG_DDEWAIT As Long = &H100
'***App Window Constants***'
Public Const WIN_NORMAL = 1 'Open Normal'
Public Const WIN_MAX = 2 'Open Maximized'
Public Const WIN_MIN = 3 'Open Minimized'
'***Error Codes***'
Private Const ERROR_SUCCESS = 32&
Private Const ERROR_NO_ASSOC = 31&
Private Const ERROR_OUT_OF_MEM = 0&
Private Const ERROR_FILE_NOT_FOUND = 2&
Private Const ERROR_PATH_NOT_FOUND = 3&
Private Const ERROR_BAD_FORMAT = 11&
' Returns 'True' if file was opened ...'
Public Function fHandleFile(ByVal stFile As String, _
ByVal lShowHow As Long, _
ByRef stRet As String, _
Optional ByVal bWaitForClose As Boolean = False) As Boolean
On Error GoTo err_Handler
Dim lRet As Long
Dim ret As Long
Dim lngProcessHandle As Long
Dim varTaskID As Variant
Dim shInfo As SHELLEXECUTEINFO
Dim retval As Long
'First try ShellExecute'
With shInfo
.cbSize = LenB(shInfo)
.lpFile = stFile
.nShow = lShowHow
If bWaitForClose Then
.fMask = SEE_MASK_FLAG_DDEWAIT + SEE_MASK_NOCLOSEPROCESS
End If
.lpVerb = "open"
End With
Call ShellExecuteEx(shInfo)
lRet = shInfo.hInstApp
If lRet > ERROR_SUCCESS And bWaitForClose = True Then
lngProcessHandle = shInfo.hProcess
Do
retval = WaitForSingleObject(lngProcessHandle, 0)
DoEvents
Loop Until retval <> 258
ret = CloseHandle(lngProcessHandle)
End If
fHandleFile = (lRet > 0)
exit_handler:
Exit Function
err_Handler:
RaiseError Err.Number, Err.Source, Err.Description
End Function
Аналогично, используя функцию внутренней оболочки():
Private Const INFINITE = &HFFFF
Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_QUERY_INFORMATION = &H400
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 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 Function SyncShell(_
ByVal PathName As String, _
ByVal WindowStyle As VbAppWinStyle) As Long
'Shell and wait. Return exit code result, raise an
'exception on any error.
Dim lngPid As Long
Dim lngHandle As Long
Dim lngExitCode As Long
lngPid = Shell(PathName, WindowStyle)
If lngPid <> 0 Then
lngHandle = OpenProcess(SYNCHRONIZE _
Or PROCESS_QUERY_INFORMATION, 0, lngPid)
If lngHandle <> 0 Then
WaitForSingleObject lngHandle, INFINITE
If GetExitCodeProcess(lngHandle, lngExitCode) <> 0 Then
SyncShell = lngExitCode
CloseHandle lngHandle
Else
CloseHandle lngHandle
Err.Raise &H8004AA00, "SyncShell", _
"Failed to retrieve exit code, error " _
& CStr(Err.LastDllError)
End If
Else
Err.Raise &H8004AA01, "SyncShell", _
"Failed to open child process"
End If
Else
Err.Raise &H8004AA02, "SyncShell", _
"Failed to Shell child process"
End If
End Function
Вот некоторые простой код, который делает это. Обратите внимание, что он передает сообщения (с помощью DoEvents), чтобы ваше приложение не было заморожено во время ожидания.
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const SYNCHRONIZE = &H100000
Private Const WAIT_TIMEOUT As Long = &H102&
Private Sub RunCommandLine(sCmdLine As String)
Dim nProcessID As Long
Dim hProcess As Long
Dim nResult As Long
nProcessID = Shell(sCmdLine, vbNormalNoFocus)
If nProcessID <> 0 Then
hProcess = OpenProcess(SYNCHRONIZE, 0, nProcessID)
If hProcess <> 0 Then
Do
DoEvents
nResult = WaitForSingleObject(hProcess, 50)
Loop Until nResult <> WAIT_TIMEOUT Or m_bStop
CloseHandle hProcess
End If
End If
End Sub
+1. Также хорошее решение. – 2011-09-13 08:33:02
Wow большое спасибо, рад, что я решил попросить здесь, а не пытаться решить его сам. – 2008-11-15 04:05:25