Results 1 to 5 of 5

Thread: How to know when an external program ended?

  1. #1

    Thread Starter
    New Member
    Join Date
    Mar 2003
    Posts
    3

    How to know when an external program ended?

    Hello to all, this is my first post in this forum. Ok here we go....I need a little help with this problem

    ***********************************
    Dim Value
    Value = Shell("xxxxxx.exe", vbNormalFocus)
    '***********************************
    The above line is used by me to call up an external program call "xxxxxx.exe". What this program does is process some results, and output the result to a data file, and closed itself.

    The content of the file will be read in the subsequent lines.

    ----------------------------------------------------------
    Note: By default, the Shell function runs other programs asynchronously. This means that a program started with Shell might not finish executing before the statements following the Shell function are executed. ~taken from MSDN
    ---------------------------------------------------------

    Now my question to fellow VB experts are, how in VB codes can I know when the program closes. I need to run the next line only after the program closed. It is important cuz the next line has a high chance of running even before the data file is generated. The data file must be generated before the next line can be run. Hope u guys can help. Thanks.
    When it is dark enough, you can see the stars.

  2. #2
    Frenzied Member
    Join Date
    Jan 2001
    Location
    Newbury, UK
    Posts
    1,878
    Look up the WaitForSingleObject API:


    The recommended way is to use CreateProcess & WaitForSingleObject.
    VB Code:
    1. 'This program needs a common dialog box, named CDBox
    2. '  (To add the Common Dialog Box to your tools menu, go to Project->Components (or press CTRL-T)
    3. '   and select Microsoft Common Dialog control)
    4. Const INFINITE = &HFFFF
    5. Const STARTF_USESHOWWINDOW = &H1
    6. Private Enum enSW
    7.     SW_HIDE = 0
    8.     SW_NORMAL = 1
    9.     SW_MAXIMIZE = 3
    10.     SW_MINIMIZE = 6
    11. End Enum
    12. Private Type PROCESS_INFORMATION
    13.     hProcess As Long
    14.     hThread As Long
    15.     dwProcessId As Long
    16.     dwThreadId As Long
    17. End Type
    18. Private Type STARTUPINFO
    19.     cb As Long
    20.     lpReserved As String
    21.     lpDesktop As String
    22.     lpTitle As String
    23.     dwX As Long
    24.     dwY As Long
    25.     dwXSize As Long
    26.     dwYSize As Long
    27.     dwXCountChars As Long
    28.     dwYCountChars As Long
    29.     dwFillAttribute As Long
    30.     dwFlags As Long
    31.     wShowWindow As Integer
    32.     cbReserved2 As Integer
    33.     lpReserved2 As Byte
    34.     hStdInput As Long
    35.     hStdOutput As Long
    36.     hStdError As Long
    37. End Type
    38. Private Type SECURITY_ATTRIBUTES
    39.     nLength As Long
    40.     lpSecurityDescriptor As Long
    41.     bInheritHandle As Long
    42. End Type
    43. Private Enum enPriority_Class
    44.     NORMAL_PRIORITY_CLASS = &H20
    45.     IDLE_PRIORITY_CLASS = &H40
    46.     HIGH_PRIORITY_CLASS = &H80
    47. End Enum
    48. Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As SECURITY_ATTRIBUTES, lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
    49. Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    50. Private Function SuperShell(ByVal App As String, ByVal WorkDir As String, dwMilliseconds As Long, ByVal start_size As enSW, ByVal Priority_Class As enPriority_Class) As Boolean
    51.     Dim pclass As Long
    52.     Dim sinfo As STARTUPINFO
    53.     Dim pinfo As PROCESS_INFORMATION
    54.     'Not used, but needed
    55.     Dim sec1 As SECURITY_ATTRIBUTES
    56.     Dim sec2 As SECURITY_ATTRIBUTES
    57.     'Set the structure size
    58.     sec1.nLength = Len(sec1)
    59.     sec2.nLength = Len(sec2)
    60.     sinfo.cb = Len(sinfo)
    61.     'Set the flags
    62.     sinfo.dwFlags = STARTF_USESHOWWINDOW
    63.     'Set the window's startup position
    64.     sinfo.wShowWindow = start_size
    65.     'Set the priority class
    66.     pclass = Priority_Class
    67.     'Start the program
    68.     If CreateProcess(vbNullString, App, sec1, sec2, False, pclass, _
    69.     0&, WorkDir, sinfo, pinfo) Then
    70.         'Wait
    71.         WaitForSingleObject pinfo.hProcess, dwMilliseconds
    72.         SuperShell = True
    73.     Else
    74.         SuperShell = False
    75.     End If
    76. End Function
    77. Private Sub Form_Load()
    78.     'KPD-Team 1998
    79.     'URL: [url]http://www.allapi.net/[/url]
    80.     'E-Mail: [email][email protected][/email]
    81.     'Set the dialog's title
    82.     CDBox.DialogTitle = "Choose an EXEC-File ..."
    83.     'Error when canceled
    84.     CDBox.CancelError = True
    85.     'Set the dialog's filter
    86.     CDBox.Filter = "EXEC-Files (*.exe)|*.exe|All files (*.*)|*.*"
    87.     'Show the 'Open File'-dialog
    88.     CDBox.ShowOpen
    89.     'Execute the program
    90.     SuperShell CDBox.filename, Left$(CDBox.filename, Len(CDBox.filename) - Len(CDBox.FileTitle)), 0, SW_NORMAL, HIGH_PRIORITY_CLASS
    91.     End
    92. End Sub

  3. #3

    Thread Starter
    New Member
    Join Date
    Mar 2003
    Posts
    3
    Thanks Jordan.

    I don't need a dialog box to open exexcutable files though. "xxxxx.exe" is all I need to run. I will try it out later in the day to see if there is any problem.
    When it is dark enough, you can see the stars.

  4. #4
    Fanatic Member
    Join Date
    Dec 2002
    Location
    North Carolina
    Posts
    734
    Just an idea, but declare value as long, shell only returns the process id of an executeable being ran so a variant really isnt needed, which is what you do when you leave a variable undeclared.

  5. #5

    Thread Starter
    New Member
    Join Date
    Mar 2003
    Posts
    3
    Thanks, the below are the codes I used eventually, and ya, it works.

    ---------------------------------------------------------------------------------
    Public Function SyncShellCmd(CmdStr As String, ApplicationFocus As Long) As Boolean
    'Run the application by the CmdStr, and exit when the program terminated, Application focus specific
    'the focus of the application. e.g vbNormalFocus
    Dim lPid As Long 'The task ID of the started program
    Dim lHnd As Long ' handle to object to wait for
    Dim lRet As Long 'Return value of WaitForSingleObject()

    SyncShellCmd = False
    If CmdStr = "" Then Exit Function
    lPid = Shell(CmdStr, ApplicationFocus)
    If lPid <> 0 Then
    'Get a handle to the shelled process.
    lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
    'If successful, wait for the application to end and close the handle.
    If lHnd <> 0 Then
    lRet = WaitForSingleObject(lHnd, INFINITE) 'no time out
    CloseHandle (lHnd)
    SyncShellCmd = True
    End If
    'MsgBox "Just terminated.", vbInformation, "Shelled Application"
    End If

    End Function
    ------------------------------------------------------------------------------
    When it is dark enough, you can see the stars.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width