2008-11-15 2 views

ответ

7

Вам нужно будет использовать вызовы 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 
+0

Wow большое спасибо, рад, что я решил попросить здесь, а не пытаться решить его сам. – 2008-11-15 04:05:25

0

Аналогично, используя функцию внутренней оболочки():

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 
6

Вот некоторые простой код, который делает это. Обратите внимание, что он передает сообщения (с помощью 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 
+0

+1. Также хорошее решение. – 2011-09-13 08:33:02