Тема: Как запустить внешнюю ЕХЕ-программу?

Помогите пожалуйста решить такую проблему:
Есть програмка на ВБА - из нее пытаюсь запустить экзешник и получается, что прога ВБА и этот экзешник отрабатывают параллельно, как будто экзешник запущен немодально (коряво на слух, но суть получается такая)!
Т.е. на экране еще висит форма из экзешника, а ВБА-шная прога уже вываливается, т.к. отработала далеко за строкой, где этот экзешник запускается.
Запускаю ехе так
RetVal1 = Shell("MyPRG.EXE", vbNormalFocus)

Re: Как запустить внешнюю ЕХЕ-программу?

можно через лисп

ThisDrawing.SendCommand "(startapp ""explorer"" (strcat ""/e,"" (getvar ""dwgprefix"")))" & vbCr
ThisDrawing.SendCommand "(startapp ""MyPRG.EXE"")" & vbCr

Re: Как запустить внешнюю ЕХЕ-программу?

Извиняюсь. Не дочитал до конца. EXE-шник действительно запускается не модально, а отдельным приложением.

Re: Как запустить внешнюю ЕХЕ-программу?

Public Declare Function GetDesktopWindow Lib "user32" () As Long
   
Public Declare Function GetWindow Lib "user32" _
  (ByVal hwnd As Long, _
   ByVal wCmd As Long) As Long
   
Public Declare Function GetWindowThreadProcessId Lib "user32" _
  (ByVal hwnd As Long, _
   lpdwProcessId As Long) As Long
Public Declare Function GetParentU Lib "user32" _
   Alias "GetParent" (ByVal hwnd As Long) As Long
   
Public Declare Function OpenProcess Lib "kernel32" _
  (ByVal dwDesiredAccess As Long, _
   ByVal bInheritHandle As Long, _
   ByVal dwProcessId As Long) As Long
   
Public Declare Function SetWindowText Lib "user32" _
   Alias "SetWindowTextA" (ByVal hwnd As Long, _
   ByVal lpString As String) As Long
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
'*********************************************************************************
'
'  Функция SVR_GethWndFromProcessID - узнает хэндл(Handle) какого-либо окна по ID процесса.
'
'  ПАРАМЕТРЫ:
'        hProcessIDToFind - целое число - ID необходимого процесса
'
'  ВОЗВРАЩАЕТ:
'        Целое число - хэндл(Handle) искомого окна
'        Или 0, если окно не найдено
'
'*********************************************************************************
Function SVR_GethWndFromProcessID(ByVal hProcessIDToFind As Long) As Long
    Dim hWndDesktop As Long
    Dim hWndChild As Long
    Dim hWndChildProcessID As Long
    Dim hWndMain As Long
    
    On Local Error GoTo GethWndFromProcessID_Error
    hWndDesktop = GetDesktopWindow()
    hWndChild = GetWindow(hWndDesktop, 5)
    
    Do While hWndChild <> 0
        Call GetWindowThreadProcessId(hWndChild, hWndChildProcessID)
        If hWndChildProcessID = hProcessIDToFind Then
            hWndMain = hWndChild
            Exit Do
        End If
        hWndChild = GetWindow(hWndChild, 2)
    Loop
    
    SVR_GethWndFromProcessID = hWndMain
    hWndMain = GetParentU(SVR_GethWndFromProcessID)
    Do While hWndMain <> 0
      SVR_GethWndFromProcessID = hWndMain
      hWndMain = GetParentU(SVR_GethWndFromProcessID)
    Loop
    
Exit Function
GethWndFromProcessID_Error:
    SVR_GethWndFromProcessID = 0
    Exit Function
    
End Function
'*********************************************************************************
'
'  Функция SVR_EXEWait - запускает на выполнение внешнюю программу и ждет ее завершения.
'                        Есть возможность изменить заголовок окна, запукаемой программы.
'
'  ПАРАМЕТРЫ:
'        cmdline - строка - команда (программа), которую надо выполнить, включая аргументы.
'        caption_str - строка - новый заголовок окна, которое будет открыто.
'            Если пустая строка "" - то заголовок не изменяется.
'        show - целое число - вид окна, которое будет открыто.
'            Допустимые значения:
'               0 - скрытый - окно не показывается
'               1 - нормальный - окно активизируется и отображается с обычными размерами
'                   в обычном положении
'               2 - свернутый - окно активизируется и отображается в свернутом виде
'               3 - на весь экран - окно активизируется и отображается на весь экран
'               4 - нормальный, не активный - окно отображается с обычными размерами, но оно не активно
'               6 - свернутый, не активный - окно отображается в свернутом виде, но оно не активно
'
'  ВОЗВРАЩАЕТ:
'        True - Если все прошло удачно
'        False - В случае ошибки
'
'*********************************************************************************
Function SVR_EXEWait(ByVal cmdline As String, _
                     ByVal caption_str As String, _
                     ByVal show As Long) As Boolean
                     
  Dim hProcessID As Long
  Dim procHandle As Long
  Dim hProcess As Long
  
  On Local Error GoTo EXEWait_Error
  
  hProcessID = Shell(cmdline, show)
  hProcess = OpenProcess((&H100000 + &H400), True, hProcessID)
  procHandle = SVR_GethWndFromProcessID(hProcessID)
  
  If (procHandle <> 0) And (hProcess <> 0) Then
    If caption_str <> "" Then
      SetWindowText procHandle, caption_str
    End If
    Call WaitForSingleObject(hProcess, -1&)
    CloseHandle hProcess
    SVR_EXEWait = True
  End If
   
EXEWait_Error:
End Function

Re: Как запустить внешнюю ЕХЕ-программу?

Это уже интереснее...
Спасибо

Re: Как запустить внешнюю ЕХЕ-программу?

> leha
Зачем открывать процесс с флагом доступа  PROCESS_QUERY_INFORMATION (=0x400)? Достаточно только SYNCHRONIZE?a (=&H100000). Во второй параметр OpenProcess () в bInheritHandle надо передавать FALSE (= 0) - в коде нигде не создаются новые  процессы.

Re: Как запустить внешнюю ЕХЕ-программу?

> Alexander
С первым согласен полностью. Это в общем-то мои первые шаги в VB (в основном использую LISP, сейчас для некоторых вещей его уже стало не хватать). Просто сначала пытался решить эту задачу через GetExitCodeProcess(), и &H400 это остаток оттуда.
А вот по второму вопрос. В документации сказано:
bInheritHandle
[in] Specifies whether the returned handle can be inherited by a new process created by the current process. If TRUE, the handle is inheritable.
Я решил, что это означает, что если запускаемый *.exe (cmdline) создает какой-то новый процесс, то я смогу дождаться в том числе и его завершения. Т.е. под "new process created by the current process" имеется ввиду процесс, который может быть создан cmdline. Или я не прав?

Re: Как запустить внешнюю ЕХЕ-программу?

> leha
НЕТ НЕ ПРАВ!
>Specifies whether the returned handle can be inherited by a new
>process created by the current process. If TRUE, the handle is
>inheritable.
- Если bInheritHandle TRUE (например, в OpenProcess()), то при создании нового (дочернего) процесса (это делается с помощью CreateProcess()) он сможет наследовать описатель. Если конечно этот дочерний процесс создавать с bInheritHandles = TRUE

Re: Как запустить внешнюю ЕХЕ-программу?

> Alexander
Спасибо, понял.

Re: Как запустить внешнюю ЕХЕ-программу?

я запускаю экзешник так: ^C^C start alex.exe;
и почитай еще www.Menu Structure.htm