Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using ShellExecute to close/stop a running VB6 exe 1

Status
Not open for further replies.

CruiseMan

Programmer
Nov 17, 2006
29
US
I have used ShellExecute to print and open files, but is there a way to stop/close a running VB6 exe that was started using a Shell function?

I have a main VB program that launched an exe using the Shell function (not ShellExecute). So far, everythings fine. What I want to do is have a way to close the program started by the Shell function if it has run for an excessive amount of time without closing.

example:
RetVal = Shell("C:\RegisterSO\RegisterSO.exe ", vbNormalFocus)

Can this be done through ShellExecute or Shell? If so, how?
 
You can use the Taskkill utility to terminate a program knowing its image name or PID.

[tt]Shell "taskkill /pid " & RetVal, vbHide[/TT]

You might want to include the /f switch which causes the process to be terminated forcefully, if the program is hung and not responding.

[tt]Shell "taskkill /f /pid " & RetVal, vbHide[/tt]

Alternatively, you can use the TerminateProcess API function to close a program. See thread222-753865 or thread222-658808.
 
Thanks, Hypetia! This works great for what I need. Super-Star!
 
Alternatively, simply add a reference to the Windows Scripting Host, and then something like the following may be useful:
Code:
[blue]Option Explicit

Dim myExec As WshExec

Private Sub Command1_Click()
    With New WshShell
        Set myExec = .Exec("C:\RegisterSO\RegisterSO.exe")
    End With
End Sub

Private Sub Command2_Click()
    myExec.Terminate
End Sub[/blue]
 
Here is the same thing using API calls to "extend" the Shell() function by converting the PID to a process handle. It is a little more elaborate than strongm's example, monitoring with a Timer control that can be used to take various actions (even though all we do here is display status and update the UI).

However...

There is often no good reason to use these API calls instead of the Script Host Object Model approach. They basically do the same thing, the extra library represents little overhead on a modern desktop, and modern anti-virus suites and local security policies seldom disable scripting seriously enough to impede it today.

The one reason to use API calls means using CreateProcess() instead of Shell() too. That way a Console Subsystem "child" process can be run without creating a Console Window, which can be annoying for some applications. "Hiding" it just isn't always good enough.

But note that I'm using Shell() here, so it works about the same as the previous example.

The child process here is a WSH script that just sits on a MsgBox call until you click Ok.

Code:
Option Explicit

Private Const SYNCHRONIZE As Long = &H100000
Private Const PROCESS_TERMINATE As Long = &H1&
Private Const PROCESS_QUERY_INFORMATION As Long = &H400&
Private Const WAIT_OBJECT_0 As Long = 0
  
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 Declare Function TerminateProcess Lib "kernel32" ( _
    ByVal hProcess As Long, _
    ByVal uExitCode As Long) As Long
  
Private Const MagicNumber As Long = &H7BADBAD7
Private hChildProcess As Long
Private T0 As Single
  
Private Sub cmdKillChild_Click()
    cmdKillChild.Enabled = False
    If TerminateProcess(hChildProcess, MagicNumber) = 0 Then
        lblStatus.Caption = "TerminateProcess failed, err " _
                          & CStr(Err.LastDllError)
    End If
End Sub
  
Private Sub cmdStartChild_Click()
    Dim ProcessId As Long
    
    'Run a WSH script hidden.
    ProcessId = Shell("wscript msgbox.vbs", vbHide)
    If ProcessId = 0 Then
        lblStatus.Caption = "Shell failed"
    Else
        hChildProcess = OpenProcess(SYNCHRONIZE _
                                 Or PROCESS_QUERY_INFORMATION _
                                 Or PROCESS_TERMINATE, _
                                    0, _
                                    ProcessId)
        If hChildProcess = 0 Then
            'Ouch, bad.  Child running but we have no handle!
            lblStatus.Caption = "OpenProcess failed, err " _
                              & CStr(Err.LastDllError)
        Else
            lblStatus.Caption = "Running"
            T0 = Timer()
            cmdStartChild.Enabled = False
            cmdKillChild.Enabled = True
            tmrMonitor.Enabled = True
        End If
    End If
End Sub
  
Private Sub tmrMonitor_Timer()
    Dim ExitCode As Long
    Dim T1 As Single
    
    If WaitForSingleObject(hChildProcess, 0) = WAIT_OBJECT_0 Then
        tmrMonitor.Enabled = False
        cmdKillChild.Enabled = False
        cmdStartChild.Enabled = True
        If GetExitCodeProcess(hChildProcess, ExitCode) = 0 Then
            CloseHandle hChildProcess
            lblStatus.Caption = "Done, GetExitCodeProcess failed, err " _
                              & CStr(Err.LastDllError)
        Else
            CloseHandle hChildProcess
            If ExitCode = MagicNumber Then
                lblStatus.Caption = "Terminated"
            Else
                lblStatus.Caption = "Done, return code " _
                                  & CStr(ExitCode)
            End If
        End If
    Else
        T1 = Timer() - T0
        If T1 < 0 Then T1 = T1 + 86400
        lblStatus.Caption = "Running " & Format$(T1, "0") & " secs"
    End If
End Sub
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top