Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 493
  • Last Modified:

VB - Shell

Hi friends,

If I use "Shell" to run an external application, it is getting executed, BUT, it is not waiting till that application gets completed.  Instead, it starts the execution of that application, and then, moves to the next line in VB.

Is there any way to run an external application, and then allow the VB cursor to the next line, ONLY when, that external application gets finished?  If there is any please help me.

Srik
0
vi_srikanth
Asked:
vi_srikanth
  • 3
  • 2
1 Solution
 
brebbelCommented:
Here you go:

The ShellAndWait subroutine uses the Shell function to start the other program. It calls the OpenProcess API function to connect to the new process and then uses WaitForSingleObject to wait until the other process terminates. Note that neither the program nor the development environment can take action during this wait.
After WaitForSingleObject returns, the ShellAndWait subroutine calls CloseHandle to close the process handle opened by OpenProcess and then exits at which point the program resumes normal execution.
 
 
 
' Start the indicated program and wait for it
' to finish, hiding while we wait.
Private Sub ShellAndWait(ByVal program_name As String, _
    ByVal window_style As VbAppWinStyle)
Dim process_id As Long
Dim process_handle As Long

    ' Start the program.
    On Error GoTo ShellError
    process_id = Shell(program_name, window_style)
    On Error GoTo 0


    ' Wait for the program to finish.
    ' Get the process handle.
    process_handle = OpenProcess(SYNCHRONIZE, 0, process_id)
    If process_handle <> 0 Then
        WaitForSingleObject process_handle, INFINITE
        CloseHandle process_handle
    End If

    Exit Sub

ShellError:
    MsgBox "Error starting task " & _
        txtProgram.Text & vbCrLf & _
        Err.Description, vbOKOnly Or vbExclamation, _
        "Error"
End Sub
 
0
 
brebbelCommented:
Sorry, forget my first post, use this example:



   Private Type STARTUPINFO
      cb As Long
      lpReserved As String
      lpDesktop As String
      lpTitle As String
      dwX As Long
      dwY As Long
      dwXSize As Long
      dwYSize As Long
      dwXCountChars As Long
      dwYCountChars As Long
      dwFillAttribute As Long
      dwFlags As Long
      wShowWindow As Integer
      cbReserved2 As Integer
      lpReserved2 As Long
      hStdInput As Long
      hStdOutput As Long
      hStdError As Long
   End Type

   Private Type PROCESS_INFORMATION
      hProcess As Long
      hThread As Long
      dwProcessID As Long
      dwThreadID As Long
   End Type

   Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
      hHandle As Long, ByVal dwMilliseconds As Long) As Long

   Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
      lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
      lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
      ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
      ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
      lpStartupInfo As STARTUPINFO, lpProcessInformation As _
      PROCESS_INFORMATION) 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 Const NORMAL_PRIORITY_CLASS = &H20&
   Private Const INFINITE = -1&

   Public Function ExecCmd(cmdline$)
      Dim proc As PROCESS_INFORMATION
      Dim start As STARTUPINFO

      ' Initialize the STARTUPINFO structure:
      start.cb = Len(start)

      ' Start the shelled application:
      ret& = CreateProcessA(vbNullString, cmdline$, 0&, 0&, 1&, _
         NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)

      ' Wait for the shelled application to finish:
         ret& = WaitForSingleObject(proc.hProcess, INFINITE)
         Call GetExitCodeProcess(proc.hProcess, ret&)
         Call CloseHandle(proc.hThread)
         Call CloseHandle(proc.hProcess)
         ExecCmd = ret&
   End Function

   Sub Form_Click()
      Dim retval As Long
      retval = ExecCmd("notepad.exe")
      MsgBox "Process Finished, Exit Code " & retval
   End Sub
0
 
vi_srikanthAuthor Commented:
But here, the application is visible.  Is there any way to hide that external application(like we have vbHide for Shell)?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
brebbelCommented:
Yes, that's also possible:

Same code, few changes:

  Private Type STARTUPINFO
     cb As Long
     lpReserved As String
     lpDesktop As String
     lpTitle As String
     dwX As Long
     dwY As Long
     dwXSize As Long
     dwYSize As Long
     dwXCountChars As Long
     dwYCountChars As Long
     dwFillAttribute As Long
     dwFlags As Long
     wShowWindow As Integer
     cbReserved2 As Integer
     lpReserved2 As Long
     hStdInput As Long
     hStdOutput As Long
     hStdError As Long
  End Type

  Private Type PROCESS_INFORMATION
     hProcess As Long
     hThread As Long
     dwProcessID As Long
     dwThreadID As Long
  End Type

  Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
     hHandle As Long, ByVal dwMilliseconds As Long) As Long

  Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
     lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
     lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
     ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
     ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
     lpStartupInfo As STARTUPINFO, lpProcessInformation As _
     PROCESS_INFORMATION) 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 Const NORMAL_PRIORITY_CLASS = &H20&
  Private Const INFINITE = -1&
  Private Const SW_HIDE = &H0&
  Private Const STARTF_USESHOWWINDOW = &H1&

  Public Function ExecCmd(cmdline$)
     Dim proc As PROCESS_INFORMATION
     Dim start As STARTUPINFO

     ' Initialize the STARTUPINFO structure:
     start.cb = Len(start)
     start.dwFlags = STARTF_USESHOWWINDOW
     start.wShowWindow = SW_HIDE


     ' Start the shelled application:
     ret& = CreateProcessA(vbNullString, cmdline$, 0&, 0&, 1&, _
        NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
       
       
     ' Wait for the shelled application to finish:
        ret& = WaitForSingleObject(proc.hProcess, INFINITE)
        Call GetExitCodeProcess(proc.hProcess, ret&)
        Call CloseHandle(proc.hThread)
        Call CloseHandle(proc.hProcess)
        ExecCmd = ret&
  End Function

  Sub Form_Click()
     Dim retval As Long
     retval = ExecCmd("notepad.exe")
     MsgBox "Process Finished, Exit Code " & retval
  End Sub

0
 
crystalbyCommented:
Try the oshell command


    Dim oShell As IWshRuntimeLibrary.IWshShell_Class
    Dim strExecute As String
   
    Set oShell = New IWshRuntimeLibrary.IWshShell_Class

    strExecute = "RunningProcess.exe"

    Call oShell.Run(strExecute, 1, True)
0
 
vi_srikanthAuthor Commented:
Thanks a lot friends.  Both the ways works perfectly.

Srik
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now